Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dxf2mtf.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/filter/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/filter/source/graphicfilter/idxf/dxf2mtf.cxx

/home/maarten/src/libreoffice/core/filter/source/graphicfilter/idxf/dxf2mtf.cxx

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 <unotools/configmgr.hxx>
22#include <vcl/gdimtf.hxx>
23#include <vcl/metaact.hxx>
24#include <vcl/virdev.hxx>
25#include <tools/poly.hxx>
26#include "dxf2mtf.hxx"
27
28#include <math.h>
29
30
31sal_uInt64 DXF2GDIMetaFile::CountEntities(const DXFEntities & rEntities)
32{
33 const DXFBasicEntity * pBE;
34 sal_uInt64 nRes;
35
36 nRes=0;
37 for (pBE=rEntities.pFirst; pBE!=nullptr; pBE=pBE->pSucc) nRes++;
38 return nRes;
39}
40
41Color DXF2GDIMetaFile::ConvertColor(sal_uInt8 nColor)
42{
43 return Color(
44 pDXF->aPalette.GetRed( nColor ),
45 pDXF->aPalette.GetGreen( nColor ),
46 pDXF->aPalette.GetBlue( nColor ) );
47}
48
49long DXF2GDIMetaFile::GetEntityColor(const DXFBasicEntity & rE)
50{
51 long nColor;
52
53 nColor=rE.nColor;
54 if (nColor==256) {
55 if (rE.m_sLayer.getLength() < 2) {
56 nColor=nParentLayerColor;
57 } else {
58 const DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
59 if (pLayer!=nullptr) nColor=pLayer->nColor;
60 else nColor=nParentLayerColor;
61 }
62 }
63 else if (nColor==0) nColor=nBlockColor;
64 return nColor;
65}
66
67DXFLineInfo DXF2GDIMetaFile::LTypeToDXFLineInfo(OString const& rLineType)
68{
69 const DXFLType * pLT;
70 DXFLineInfo aDXFLineInfo;
71
72 pLT = pDXF->aTables.SearchLType(rLineType);
73 if (pLT==nullptr || pLT->nDashCount == 0) {
74 aDXFLineInfo.eStyle = LineStyle::Solid;
75 }
76 else {
77 aDXFLineInfo.eStyle = LineStyle::Dash;
78 for (long i=0; i < (pLT->nDashCount); i++) {
79 const double x = pLT->fDash[i] * pDXF->getGlobalLineTypeScale();
80 if ( x >= 0.0 ) {
81 if ( aDXFLineInfo.nDotCount == 0 ) {
82 aDXFLineInfo.nDotCount ++;
83 aDXFLineInfo.fDotLen = x;
84 }
85 else if ( aDXFLineInfo.fDotLen == x ) {
86 aDXFLineInfo.nDotCount ++;
87 }
88 else if ( aDXFLineInfo.nDashCount == 0 ) {
89 aDXFLineInfo.nDashCount ++;
90 aDXFLineInfo.fDashLen = x;
91 }
92 else if ( aDXFLineInfo.fDashLen == x ) {
93 aDXFLineInfo.nDashCount ++;
94 }
95 else {
96 // It is impossible to be converted.
97 }
98 }
99 else {
100 if ( aDXFLineInfo.fDistance == 0 ) {
101 aDXFLineInfo.fDistance = -1 * x;
102 }
103 else {
104 // It is impossible to be converted.
105 }
106 }
107
108 }
109 }
110
111 return aDXFLineInfo;
112}
113
114DXFLineInfo DXF2GDIMetaFile::GetEntityDXFLineInfo(const DXFBasicEntity & rE)
115{
116 DXFLineInfo aDXFLineInfo;
117
118 aDXFLineInfo.eStyle = LineStyle::Solid;
119 aDXFLineInfo.nDashCount = 0;
120 aDXFLineInfo.fDashLen = 0;
121 aDXFLineInfo.nDotCount = 0;
122 aDXFLineInfo.fDotLen = 0;
123 aDXFLineInfo.fDistance = 0;
124
125 if (rE.m_sLineType == "BYLAYER") {
126 if (rE.m_sLayer.getLength() < 2) {
127 aDXFLineInfo=aParentLayerDXFLineInfo;
128 } else {
129 const DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
130 if (pLayer!=nullptr) {
131 aDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
132 }
133 else aDXFLineInfo=aParentLayerDXFLineInfo;
134 }
135 }
136 else if (rE.m_sLineType == "BYBLOCK") {
137 aDXFLineInfo=aBlockDXFLineInfo;
138 }
139 else {
140 aDXFLineInfo = LTypeToDXFLineInfo(rE.m_sLineType);
141 }
142 return aDXFLineInfo;
143}
144
145
146bool DXF2GDIMetaFile::SetLineAttribute(const DXFBasicEntity & rE)
147{
148 long nColor;
149 Color aColor;
150
151 nColor=GetEntityColor(rE);
152 if (nColor<0) return false;
153 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
154
155 if (aActLineColor!=aColor) {
156 aActLineColor = aColor;
157 pVirDev->SetLineColor( aActLineColor );
158 }
159
160 if (aActFillColor!=COL_TRANSPARENT) {
161 aActFillColor = COL_TRANSPARENT;
162 pVirDev->SetFillColor(aActFillColor);
163 }
164 return true;
165}
166
167
168bool DXF2GDIMetaFile::SetAreaAttribute(const DXFBasicEntity & rE)
169{
170 long nColor;
171 Color aColor;
172
173 nColor=GetEntityColor(rE);
174 if (nColor<0) return false;
175 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
176
177 if (aActLineColor!=aColor) {
178 aActLineColor = aColor;
179 pVirDev->SetLineColor( aActLineColor );
180 }
181
182 if ( aActFillColor == COL_TRANSPARENT || aActFillColor != aColor) {
183 aActFillColor = aColor;
184 pVirDev->SetFillColor( aActFillColor );
185 }
186 return true;
187}
188
189
190bool DXF2GDIMetaFile::SetFontAttribute(const DXFBasicEntity & rE, short nAngle, sal_uInt16 nHeight)
191{
192 long nColor;
193 Color aColor;
194 vcl::Font aFont;
195
196 nAngle=-nAngle;
197 while (nAngle>=3600) nAngle-=3600;
198 while (nAngle<0) nAngle+=3600;
199
200 nColor=GetEntityColor(rE);
201 if (nColor<0) return false;
202 aColor=ConvertColor(static_cast<sal_uInt8>(nColor));
203
204 aFont.SetColor(aColor);
205 aFont.SetTransparent(true);
206 aFont.SetFamily(FAMILY_SWISS);
207 aFont.SetFontSize(Size(0,nHeight));
208 aFont.SetAlignment(ALIGN_BASELINE);
209 aFont.SetOrientation(nAngle);
210 if (aActFont!=aFont) {
211 aActFont=aFont;
212 pVirDev->SetFont(aActFont);
213 }
214
215 return true;
216}
217
218
219void DXF2GDIMetaFile::DrawLineEntity(const DXFLineEntity & rE, const DXFTransform & rTransform)
220{
221 if (!SetLineAttribute(rE))
222 return;
223
224 Point aP0,aP1;
225 rTransform.Transform(rE.aP0,aP0);
226 rTransform.Transform(rE.aP1,aP1);
227
228 DXFLineInfo aDXFLineInfo=GetEntityDXFLineInfo(rE);
229 LineInfo aLineInfo;
230 aLineInfo = rTransform.Transform(aDXFLineInfo);
231
232 pVirDev->DrawLine(aP0,aP1,aLineInfo);
233 if (rE.fThickness!=0) {
234 Point aP2,aP3;
235 rTransform.Transform(rE.aP0+DXFVector(0,0,rE.fThickness),aP2);
236 rTransform.Transform(rE.aP1+DXFVector(0,0,rE.fThickness),aP3);
237 DrawLine(aP2,aP3);
238 DrawLine(aP0,aP2);
239 DrawLine(aP1,aP3);
240 }
241}
242
243
244void DXF2GDIMetaFile::DrawPointEntity(const DXFPointEntity & rE, const DXFTransform & rTransform)
245{
246
247 if (SetLineAttribute(rE)) {
248 Point aP0;
249 rTransform.Transform(rE.aP0,aP0);
250 if (rE.fThickness==0) pVirDev->DrawPixel(aP0);
251 else {
252 Point aP1;
253 rTransform.Transform(rE.aP0+DXFVector(0,0,rE.fThickness),aP1);
254 DrawLine(aP0,aP1);
255 }
256 }
257}
258
259
260void DXF2GDIMetaFile::DrawCircleEntity(const DXFCircleEntity & rE, const DXFTransform & rTransform)
261{
262 double frx,fry;
263 sal_uInt16 nPoints,i;
264 DXFVector aC;
265
266 if (!SetLineAttribute(rE)) return;
267 rTransform.Transform(rE.aP0,aC);
268 if (rE.fThickness==0 && rTransform.TransCircleToEllipse(rE.fRadius,frx,fry)) {
269 pVirDev->DrawEllipse(
270 tools::Rectangle(static_cast<long>(aC.fx-frx+0.5),static_cast<long>(aC.fy-fry+0.5),
271 static_cast<long>(aC.fx+frx+0.5),static_cast<long>(aC.fy+fry+0.5)));
272 }
273 else {
274 double fAng;
275 nPoints=OptPointsPerCircle;
276 tools::Polygon aPoly(nPoints);
277 for (i=0; i<nPoints; i++) {
278 fAng=2*3.14159265359/static_cast<double>(nPoints-1)*static_cast<double>(i);
279 rTransform.Transform(
280 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),0),
281 aPoly[i]
282 );
283 }
284 pVirDev->DrawPolyLine(aPoly);
285 if (rE.fThickness!=0) {
286 tools::Polygon aPoly2(nPoints);
287 for (i=0; i<nPoints; i++) {
288 fAng=2*3.14159265359/static_cast<double>(nPoints-1)*static_cast<double>(i);
289 rTransform.Transform(
290 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),rE.fThickness),
291 aPoly2[i]
292 );
293
294 }
295 pVirDev->DrawPolyLine(aPoly2);
296 for (i=0; i<nPoints-1; i++) DrawLine(aPoly[i],aPoly2[i]);
297 }
298 }
299}
300
301void DXF2GDIMetaFile::DrawLine(const Point& rA, const Point& rB)
302{
303 if (utl::ConfigManager::IsFuzzing())
304 return;
305 GDIMetaFile* pMetaFile = pVirDev->GetConnectMetaFile();
306 assert(pMetaFile)(static_cast <bool> (pMetaFile) ? void (0) : __assert_fail
("pMetaFile", "/home/maarten/src/libreoffice/core/filter/source/graphicfilter/idxf/dxf2mtf.cxx"
, 306, __extension__ __PRETTY_FUNCTION__))
;
307 //use AddAction instead of OutputDevice::DrawLine so that we can explicitly share
308 //the aDefaultLineInfo between the MetaLineActions to reduce memory use
309 pMetaFile->AddAction(new MetaLineAction(rA, rB, aDefaultLineInfo));
310}
311
312void DXF2GDIMetaFile::DrawArcEntity(const DXFArcEntity & rE, const DXFTransform & rTransform)
313{
314 double frx,fry;
315 sal_uInt16 nPoints,i;
316 DXFVector aC;
317
318 if (!SetLineAttribute(rE)) return;
319 double fA1=rE.fStart;
320 double fdA=rE.fEnd-fA1;
321 fdA = fmod(fdA, 360.0);
322 if (fdA<=0) fdA+=360.0;
323 rTransform.Transform(rE.aP0,aC);
324 if (rE.fThickness==0 && fdA>5.0 && rTransform.TransCircleToEllipse(rE.fRadius,frx,fry)) {
325 DXFVector aVS(cos(fA1/180.0*3.14159265359),sin(fA1/180.0*3.14159265359),0.0);
326 aVS*=rE.fRadius;
327 aVS+=rE.aP0;
328 DXFVector aVE(cos((fA1+fdA)/180.0*3.14159265359),sin((fA1+fdA)/180.0*3.14159265359),0.0);
329 aVE*=rE.fRadius;
330 aVE+=rE.aP0;
331 Point aPS,aPE;
332 if (rTransform.Mirror()) {
333 rTransform.Transform(aVS,aPS);
334 rTransform.Transform(aVE,aPE);
335 }
336 else {
337 rTransform.Transform(aVS,aPE);
338 rTransform.Transform(aVE,aPS);
339 }
340 pVirDev->DrawArc(
341 tools::Rectangle(static_cast<long>(aC.fx-frx+0.5),static_cast<long>(aC.fy-fry+0.5),
342 static_cast<long>(aC.fx+frx+0.5),static_cast<long>(aC.fy+fry+0.5)),
343 aPS,aPE
344 );
345 }
346 else {
347 double fAng;
348 nPoints=static_cast<sal_uInt16>(fdA/360.0*static_cast<double>(OptPointsPerCircle)+0.5);
349 if (nPoints<2) nPoints=2;
350 tools::Polygon aPoly(nPoints);
351 for (i=0; i<nPoints; i++) {
352 fAng=3.14159265359/180.0 * ( fA1 + fdA/static_cast<double>(nPoints-1)*static_cast<double>(i) );
353 rTransform.Transform(
354 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),0),
355 aPoly[i]
356 );
357 }
358 pVirDev->DrawPolyLine(aPoly);
359 if (rE.fThickness!=0) {
360 tools::Polygon aPoly2(nPoints);
361 for (i=0; i<nPoints; i++) {
362 fAng=3.14159265359/180.0 * ( fA1 + fdA/static_cast<double>(nPoints-1)*static_cast<double>(i) );
363 rTransform.Transform(
364 rE.aP0+DXFVector(rE.fRadius*cos(fAng),rE.fRadius*sin(fAng),rE.fThickness),
365 aPoly2[i]
366 );
367 }
368 pVirDev->DrawPolyLine(aPoly2);
369 for (i=0; i<nPoints; i++)
370 DrawLine(aPoly[i], aPoly2[i]);
371 }
372 }
373}
374
375void DXF2GDIMetaFile::DrawTraceEntity(const DXFTraceEntity & rE, const DXFTransform & rTransform)
376{
377 if (!SetLineAttribute(rE))
378 return;
379
380 tools::Polygon aPoly(4);
381 rTransform.Transform(rE.aP0,aPoly[0]);
382 rTransform.Transform(rE.aP1,aPoly[1]);
383 rTransform.Transform(rE.aP3,aPoly[2]);
384 rTransform.Transform(rE.aP2,aPoly[3]);
385 pVirDev->DrawPolygon(aPoly);
386 if (rE.fThickness!=0) {
387 sal_uInt16 i;
388 tools::Polygon aPoly2(4);
389 DXFVector aVAdd(0,0,rE.fThickness);
390 rTransform.Transform(rE.aP0+aVAdd,aPoly2[0]);
391 rTransform.Transform(rE.aP1+aVAdd,aPoly2[1]);
392 rTransform.Transform(rE.aP3+aVAdd,aPoly2[2]);
393 rTransform.Transform(rE.aP2+aVAdd,aPoly2[3]);
394 pVirDev->DrawPolygon(aPoly2);
395 for (i=0; i<4; i++) DrawLine(aPoly[i],aPoly2[i]);
396 }
397}
398
399
400void DXF2GDIMetaFile::DrawSolidEntity(const DXFSolidEntity & rE, const DXFTransform & rTransform)
401{
402 if (!SetAreaAttribute(rE))
403 return;
404
405 sal_uInt16 nN;
406 if (rE.aP2==rE.aP3) nN=3; else nN=4;
407 tools::Polygon aPoly(nN);
408 rTransform.Transform(rE.aP0,aPoly[0]);
409 rTransform.Transform(rE.aP1,aPoly[1]);
410 rTransform.Transform(rE.aP3,aPoly[2]);
411 if (nN>3) rTransform.Transform(rE.aP2,aPoly[3]);
412 pVirDev->DrawPolygon(aPoly);
413 if (rE.fThickness==0) return;
414
415 tools::Polygon aPoly2(nN);
416 DXFVector aVAdd(0,0,rE.fThickness);
417 rTransform.Transform(rE.aP0+aVAdd,aPoly2[0]);
418 rTransform.Transform(rE.aP1+aVAdd,aPoly2[1]);
419 rTransform.Transform(rE.aP3+aVAdd,aPoly2[2]);
420 if (nN>3) rTransform.Transform(rE.aP2+aVAdd,aPoly2[3]);
421 pVirDev->DrawPolygon(aPoly2);
422 if (SetLineAttribute(rE)) {
423 sal_uInt16 i;
424 for (i=0; i<nN; i++) DrawLine(aPoly[i],aPoly2[i]);
425 }
426}
427
428
429void DXF2GDIMetaFile::DrawTextEntity(const DXFTextEntity & rE, const DXFTransform & rTransform)
430{
431 DXFVector aV;
432 double fA;
433 sal_uInt16 nHeight;
434 short nAng;
435 DXFTransform aT( DXFTransform(rE.fXScale,rE.fHeight,1.0,rE.fRotAngle,rE.aP0), rTransform );
436 aT.TransDir(DXFVector(0,1,0),aV);
437 nHeight=static_cast<sal_uInt16>(aV.Abs()+0.5);
438 fA=aT.CalcRotAngle();
439 nAng=static_cast<short>(fA*10.0+0.5);
440 aT.TransDir(DXFVector(1,0,0),aV);
441 if ( SetFontAttribute( rE,nAng, nHeight ) )
442 {
443 OUString const aUString(pDXF->ToOUString(rE.m_sText));
444 Point aPt;
445 aT.Transform( DXFVector( 0, 0, 0 ), aPt );
446 pVirDev->DrawText( aPt, aUString );
447 }
448}
449
450
451void DXF2GDIMetaFile::DrawInsertEntity(const DXFInsertEntity & rE, const DXFTransform & rTransform)
452{
453 const DXFBlock * pB;
454 pB=pDXF->aBlocks.Search(rE.m_sName);
455 if (pB==nullptr)
456 return;
457
458 DXFTransform aDXFTransform1(1.0,1.0,1.0,DXFVector(0.0,0.0,0.0)-pB->aBasePoint);
459 DXFTransform aDXFTransform2(rE.fXScale,rE.fYScale,rE.fZScale,rE.fRotAngle,rE.aP0);
460 DXFTransform aT(
461 DXFTransform( aDXFTransform1, aDXFTransform2 ),
462 rTransform
463 );
464 long nSavedBlockColor, nSavedParentLayerColor;
465 DXFLineInfo aSavedBlockDXFLineInfo, aSavedParentLayerDXFLineInfo;
466 nSavedBlockColor=nBlockColor;
467 nSavedParentLayerColor=nParentLayerColor;
468 aSavedBlockDXFLineInfo=aBlockDXFLineInfo;
469 aSavedParentLayerDXFLineInfo=aParentLayerDXFLineInfo;
470 nBlockColor=GetEntityColor(rE);
471 aBlockDXFLineInfo=GetEntityDXFLineInfo(rE);
472 if (rE.m_sLayer.getLength() > 1) {
473 DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
474 if (pLayer!=nullptr) {
475 nParentLayerColor=pLayer->nColor;
476 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
477 }
478 }
479 DrawEntities(*pB,aT);
480 aBlockDXFLineInfo=aSavedBlockDXFLineInfo;
481 aParentLayerDXFLineInfo=aSavedParentLayerDXFLineInfo;
482 nBlockColor=nSavedBlockColor;
483 nParentLayerColor=nSavedParentLayerColor;
484}
485
486
487void DXF2GDIMetaFile::DrawAttribEntity(const DXFAttribEntity & rE, const DXFTransform & rTransform)
488{
489 if ((rE.nAttrFlags&1)!=0)
490 return;
491
492 DXFVector aV;
493 double fA;
494 sal_uInt16 nHeight;
495 short nAng;
496 DXFTransform aT( DXFTransform( rE.fXScale, rE.fHeight, 1.0, rE.fRotAngle, rE.aP0 ), rTransform );
497 aT.TransDir(DXFVector(0,1,0),aV);
498 nHeight=static_cast<sal_uInt16>(aV.Abs()+0.5);
499 fA=aT.CalcRotAngle();
500 nAng=static_cast<short>(fA*10.0+0.5);
501 aT.TransDir(DXFVector(1,0,0),aV);
502 if (SetFontAttribute(rE,nAng,nHeight))
503 {
504 OUString const aUString(pDXF->ToOUString(rE.m_sText));
505 Point aPt;
506 aT.Transform( DXFVector( 0, 0, 0 ), aPt );
507 pVirDev->DrawText( aPt, aUString );
508 }
509}
510
511
512void DXF2GDIMetaFile::DrawPolyLineEntity(const DXFPolyLineEntity & rE, const DXFTransform & rTransform)
513{
514 sal_uInt16 i,nPolySize;
515 const DXFBasicEntity * pBE;
516
517 nPolySize=0;
518 pBE=rE.pSucc;
519 while (pBE!=nullptr && pBE->eType==DXF_VERTEX) {
520 nPolySize++;
521 pBE=pBE->pSucc;
522 }
523 if (nPolySize<2)
524 return;
525 tools::Polygon aPoly(nPolySize);
526 pBE=rE.pSucc;
527 for (i=0; i<nPolySize; i++) {
528 rTransform.Transform(static_cast<const DXFVertexEntity*>(pBE)->aP0,aPoly[i]);
529 pBE=pBE->pSucc;
530 }
531
532 if (!SetLineAttribute(rE))
533 return;
534
535 if ((rE.nFlags&1)!=0) pVirDev->DrawPolygon(aPoly);
536 else pVirDev->DrawPolyLine(aPoly);
537 if (rE.fThickness==0)
538 return;
539
540 tools::Polygon aPoly2(nPolySize);
541 pBE=rE.pSucc;
542 for (i=0; i<nPolySize; i++) {
543 rTransform.Transform(
544 (static_cast<const DXFVertexEntity*>(pBE)->aP0)+DXFVector(0,0,rE.fThickness),
545 aPoly2[i]
546 );
547 pBE=pBE->pSucc;
548 }
549 if ((rE.nFlags&1)!=0) pVirDev->DrawPolygon(aPoly2);
550 else pVirDev->DrawPolyLine(aPoly2);
551 for (i=0; i<nPolySize; i++) DrawLine(aPoly[i],aPoly2[i]);
552}
553
554void DXF2GDIMetaFile::DrawLWPolyLineEntity(const DXFLWPolyLineEntity & rE, const DXFTransform & rTransform )
555{
556 sal_Int32 nPolySize = rE.aP.size();
557 if (!nPolySize)
558 return;
559
560 tools::Polygon aPoly( static_cast<sal_uInt16>(nPolySize));
561 for (sal_Int32 i = 0; i < nPolySize; ++i)
562 {
563 rTransform.Transform( rE.aP[ static_cast<sal_uInt16>(i) ], aPoly[ static_cast<sal_uInt16>(i) ] );
564 }
565 if ( SetLineAttribute( rE ) )
566 {
567 if ( ( rE.nFlags & 1 ) != 0 )
568 pVirDev->DrawPolygon( aPoly );
569 else
570 pVirDev->DrawPolyLine( aPoly );
571 }
572}
573
574void DXF2GDIMetaFile::DrawHatchEntity(const DXFHatchEntity & rE, const DXFTransform & rTransform )
575{
576 if ( !rE.nBoundaryPathCount )
577 return;
578
579 SetAreaAttribute( rE );
580 sal_Int32 j = 0;
581 tools::PolyPolygon aPolyPoly;
582 for ( j = 0; j < rE.nBoundaryPathCount; j++ )
583 {
584 std::vector< Point > aPtAry;
585 const DXFBoundaryPathData& rPathData = rE.pBoundaryPathData[ j ];
586 if ( rPathData.bIsPolyLine )
587 {
588 for (const auto& a : rPathData.aP)
589 {
590 Point aPt;
591 rTransform.Transform(a, aPt);
592 aPtAry.push_back( aPt );
593 }
594 }
595 else
596 {
597 for ( auto& rEdge : rPathData.aEdges )
598 {
599 const DXFEdgeType* pEdge = rEdge.get();
600 switch( pEdge->nEdgeType )
601 {
602 case 1 :
603 {
604 Point aPt;
605 rTransform.Transform( static_cast<const DXFEdgeTypeLine*>(pEdge)->aStartPoint, aPt );
606 aPtAry.push_back( aPt );
607 rTransform.Transform( static_cast<const DXFEdgeTypeLine*>(pEdge)->aEndPoint, aPt );
608 aPtAry.push_back( aPt );
609 }
610 break;
611 case 2 :
612 case 3 :
613 case 4 :
614 break;
615 }
616 }
617 }
618 sal_uInt16 i, nSize = static_cast<sal_uInt16>(aPtAry.size());
619 if ( nSize )
620 {
621 tools::Polygon aPoly( nSize );
622 for ( i = 0; i < nSize; i++ )
623 aPoly[ i ] = aPtAry[ i ];
624 aPolyPoly.Insert( aPoly );
625 }
626 }
627 if ( aPolyPoly.Count() )
628 pVirDev->DrawPolyPolygon( aPolyPoly );
629}
630
631void DXF2GDIMetaFile::Draw3DFaceEntity(const DXF3DFaceEntity & rE, const DXFTransform & rTransform)
632{
633 sal_uInt16 nN,i;
634 if (!SetLineAttribute(rE))
635 return;
636
637 if (rE.aP2==rE.aP3) nN=3; else nN=4;
638 tools::Polygon aPoly(nN);
639 rTransform.Transform(rE.aP0,aPoly[0]);
640 rTransform.Transform(rE.aP1,aPoly[1]);
641 rTransform.Transform(rE.aP2,aPoly[2]);
642 if (nN>3) rTransform.Transform(rE.aP3,aPoly[3]);
643 if ((rE.nIEFlags&0x0f)==0) pVirDev->DrawPolygon(aPoly);
644 else {
645 for (i=0; i<nN; i++) {
646 if ( (rE.nIEFlags & (1<<i)) == 0 ) {
647 DrawLine(aPoly[i],aPoly[(i+1)%nN]);
648 }
649 }
650 }
651}
652
653void DXF2GDIMetaFile::DrawDimensionEntity(const DXFDimensionEntity & rE, const DXFTransform & rTransform)
654{
655 const DXFBlock * pB;
656 pB=pDXF->aBlocks.Search(rE.m_sPseudoBlock);
657 if (pB==nullptr)
658 return;
659
660 DXFTransform aT(
661 DXFTransform(1.0,1.0,1.0,DXFVector(0.0,0.0,0.0)-pB->aBasePoint),
662 rTransform
663 );
664 long nSavedBlockColor, nSavedParentLayerColor;
665 DXFLineInfo aSavedBlockDXFLineInfo, aSavedParentLayerDXFLineInfo;
666 nSavedBlockColor=nBlockColor;
667 nSavedParentLayerColor=nParentLayerColor;
668 aSavedBlockDXFLineInfo=aBlockDXFLineInfo;
669 aSavedParentLayerDXFLineInfo=aParentLayerDXFLineInfo;
670 nBlockColor=GetEntityColor(rE);
671 aBlockDXFLineInfo=GetEntityDXFLineInfo(rE);
672 if (rE.m_sLayer.getLength() > 1) {
673 DXFLayer * pLayer=pDXF->aTables.SearchLayer(rE.m_sLayer);
674 if (pLayer!=nullptr) {
675 nParentLayerColor=pLayer->nColor;
676 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
677 }
678 }
679 DrawEntities(*pB,aT);
680 aBlockDXFLineInfo=aSavedBlockDXFLineInfo;
681 aParentLayerDXFLineInfo=aSavedParentLayerDXFLineInfo;
682 nBlockColor=nSavedBlockColor;
683 nParentLayerColor=nSavedParentLayerColor;
684}
685
686
687void DXF2GDIMetaFile::DrawEntities(const DXFEntities & rEntities,
688 const DXFTransform & rTransform)
689{
690 if (rEntities.mbBeingDrawn)
691 return;
692 rEntities.mbBeingDrawn = true;
693
694 DXFTransform aET;
695 const DXFTransform * pT;
696
697 const DXFBasicEntity * pE=rEntities.pFirst;
698
699 while (pE!=nullptr && bStatus) {
700 if (pE->nSpace==0) {
701 if (pE->aExtrusion.fz==1.0) {
702 pT=&rTransform;
703 }
704 else {
705 aET=DXFTransform(DXFTransform(pE->aExtrusion),rTransform);
706 pT=&aET;
707 }
708 switch (pE->eType) {
709 case DXF_LINE:
710 DrawLineEntity(static_cast<const DXFLineEntity&>(*pE),*pT);
711 break;
712 case DXF_POINT:
713 DrawPointEntity(static_cast<const DXFPointEntity&>(*pE),*pT);
714 break;
715 case DXF_CIRCLE:
716 DrawCircleEntity(static_cast<const DXFCircleEntity&>(*pE),*pT);
717 break;
718 case DXF_ARC:
719 DrawArcEntity(static_cast<const DXFArcEntity&>(*pE),*pT);
720 break;
721 case DXF_TRACE:
722 DrawTraceEntity(static_cast<const DXFTraceEntity&>(*pE),*pT);
723 break;
724 case DXF_SOLID:
725 DrawSolidEntity(static_cast<const DXFSolidEntity&>(*pE),*pT);
726 break;
727 case DXF_TEXT:
728 DrawTextEntity(static_cast<const DXFTextEntity&>(*pE),*pT);
729 break;
730 case DXF_INSERT:
731 DrawInsertEntity(static_cast<const DXFInsertEntity&>(*pE),*pT);
732 break;
733 case DXF_ATTRIB:
734 DrawAttribEntity(static_cast<const DXFAttribEntity&>(*pE),*pT);
735 break;
736 case DXF_POLYLINE:
737 DrawPolyLineEntity(static_cast<const DXFPolyLineEntity&>(*pE),*pT);
738 break;
739 case DXF_LWPOLYLINE :
740 DrawLWPolyLineEntity(static_cast<const DXFLWPolyLineEntity&>(*pE), *pT);
741 break;
742 case DXF_HATCH :
743 DrawHatchEntity(static_cast<const DXFHatchEntity&>(*pE), *pT);
744 break;
745 case DXF_3DFACE:
746 Draw3DFaceEntity(static_cast<const DXF3DFaceEntity&>(*pE),*pT);
747 break;
748 case DXF_DIMENSION:
749 DrawDimensionEntity(static_cast<const DXFDimensionEntity&>(*pE),*pT);
750 break;
751 default:
752 break; // four other values not handled -Wall
753 }
754 }
755 pE=pE->pSucc;
756 }
757
758 rEntities.mbBeingDrawn = false;
759}
760
761
762DXF2GDIMetaFile::DXF2GDIMetaFile()
763 : pVirDev(nullptr)
764 , pDXF(nullptr)
765 , bStatus(false)
766 , OptPointsPerCircle(0)
767 , nMinPercent(0)
768 , nMaxPercent(0)
769 , nLastPercent(0)
770 , nMainEntitiesCount(0)
771 , nBlockColor(0)
772 , nParentLayerColor(0)
773{
774}
775
776
777DXF2GDIMetaFile::~DXF2GDIMetaFile()
778{
779}
780
781
782bool DXF2GDIMetaFile::Convert(const DXFRepresentation & rDXF, GDIMetaFile & rMTF, sal_uInt16 nminpercent, sal_uInt16 nmaxpercent)
783{
784 double fWidth,fHeight,fScale(0.0);
785 DXFTransform aTransform;
786 Size aPrefSize;
787 const DXFLayer * pLayer;
788 const DXFVPort * pVPort;
789
790 pVirDev = VclPtr<VirtualDevice>::Create();
791 pDXF = &rDXF;
792 bStatus = true;
793
794 OptPointsPerCircle=50;
795
796 nMinPercent=nminpercent;
797 nMaxPercent=nmaxpercent;
798 nLastPercent=nMinPercent;
799 nMainEntitiesCount=CountEntities(pDXF->aEntities);
800
801 nBlockColor=7;
802 aBlockDXFLineInfo.eStyle = LineStyle::Solid;
803 aBlockDXFLineInfo.nDashCount = 0;
804 aBlockDXFLineInfo.fDashLen = 0;
805 aBlockDXFLineInfo.nDotCount = 0;
806 aBlockDXFLineInfo.fDotLen = 0;
807 aBlockDXFLineInfo.fDistance = 0;
808
809 pLayer=pDXF->aTables.SearchLayer("0");
810 if (pLayer!=nullptr) {
1
Assuming the condition is false
2
Taking false branch
811 nParentLayerColor=pLayer->nColor & 0xff;
812 aParentLayerDXFLineInfo = LTypeToDXFLineInfo(pLayer->m_sLineType);
813 }
814 else {
815 nParentLayerColor=7;
816 aParentLayerDXFLineInfo.eStyle = LineStyle::Solid;
817 aParentLayerDXFLineInfo.nDashCount = 0;
818 aParentLayerDXFLineInfo.fDashLen = 0;
819 aParentLayerDXFLineInfo.nDotCount = 0;
820 aParentLayerDXFLineInfo.fDotLen = 0;
821 aParentLayerDXFLineInfo.fDistance = 0;
822 }
823
824 pVirDev->EnableOutput(false);
825 if (!utl::ConfigManager::IsFuzzing()) // for fuzzing don't bother recording the drawing
3
Assuming the condition is false
4
Taking false branch
826 rMTF.Record(pVirDev);
827
828 aActLineColor = pVirDev->GetLineColor();
829 aActFillColor = pVirDev->GetFillColor();
830 aActFont = pVirDev->GetFont();
831
832 pVPort=pDXF->aTables.SearchVPort("*ACTIVE");
833 if (pVPort!=nullptr) {
5
Assuming the condition is false
6
Taking false branch
834 if (pVPort->aDirection.fx==0 && pVPort->aDirection.fy==0)
835 pVPort=nullptr;
836 }
837
838 if (pVPort==nullptr) {
7
Taking true branch
839 if (pDXF->aBoundingBox.bEmpty)
8
Assuming field 'bEmpty' is false
9
Taking false branch
840 bStatus=false;
841 else {
842 fWidth=pDXF->aBoundingBox.fMaxX-pDXF->aBoundingBox.fMinX;
843 fHeight=pDXF->aBoundingBox.fMaxY-pDXF->aBoundingBox.fMinY;
844 if (fWidth<=0 || fHeight<=0) {
10
Assuming 'fWidth' is > 0
11
Assuming 'fHeight' is > 0
12
Taking false branch
845 bStatus=false;
846 }
847 else {
848 if (fWidth>fHeight)
13
Assuming 'fWidth' is <= 'fHeight'
14
Taking false branch
849 fScale=10000.0/fWidth;
850 else
851 fScale=10000.0/fHeight;
852 aTransform=DXFTransform(fScale,-fScale,fScale,
853 DXFVector(-pDXF->aBoundingBox.fMinX*fScale,
854 pDXF->aBoundingBox.fMaxY*fScale,
855 -pDXF->aBoundingBox.fMinZ*fScale));
856 }
857 aPrefSize.setWidth(static_cast<long>(fWidth*fScale+1.5) );
858 aPrefSize.setHeight(static_cast<long>(fHeight*fScale+1.5) );
859 }
860 }
861 else {
862 fHeight=pVPort->fHeight;
863 fWidth=fHeight*pVPort->fAspectRatio;
864 if (fWidth<=0 || fHeight<=0) {
865 bStatus=false;
866 } else {
867 if (fWidth>fHeight)
868 fScale=10000.0/fWidth;
869 else
870 fScale=10000.0/fHeight;
871 aTransform=DXFTransform(
872 DXFTransform(pVPort->aDirection,pVPort->aTarget),
873 DXFTransform(
874 DXFTransform(1.0,-1.0,1.0,DXFVector(fWidth/2-pVPort->fCenterX,fHeight/2+pVPort->fCenterY,0)),
875 DXFTransform(fScale,fScale,fScale,DXFVector(0,0,0))
876 )
877 );
878 }
879 aPrefSize.setWidth(static_cast<long>(fWidth*fScale+1.5) );
880 aPrefSize.setHeight(static_cast<long>(fHeight*fScale+1.5) );
881 }
882
883 if (bStatus)
15
Assuming field 'bStatus' is false
16
Taking false branch
884 DrawEntities(pDXF->aEntities,aTransform);
885
886 rMTF.Stop();
887
888 if ( bStatus
16.1
Field 'bStatus' is false
16.1
Field 'bStatus' is false
16.1
Field 'bStatus' is false
16.1
Field 'bStatus' is false
)
17
Taking false branch
889 {
890 rMTF.SetPrefSize( aPrefSize );
891 // simply set map mode to 1/100-mm (1/10-mm) if the graphic
892 // does not get not too small (<0.5cm)
893 if( ( aPrefSize.Width() < 500 ) && ( aPrefSize.Height() < 500 ) )
894 rMTF.SetPrefMapMode( MapMode( MapUnit::Map10thMM ) );
895 else
896 rMTF.SetPrefMapMode( MapMode( MapUnit::Map100thMM ) );
897 }
898
899 pVirDev.disposeAndClear();
18
Calling 'VclPtr::disposeAndClear'
900 return bStatus;
901}
902
903
904/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
19
Calling copy constructor for 'Reference<VirtualDevice>'
22
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
23
Calling 'Reference::clear'
30
Returning; memory was released
205 if (aTmp.get()) {
31
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
20
Assuming field 'm_pBody' is non-null
21
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
23.1
Field 'm_pBody' is non-null
)
24
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
25
Calling 'VclReferenceBase::release'
29
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
32
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
26
Assuming the condition is true
27
Taking true branch
40 delete this;
28
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif