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 svmconverter.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 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -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 VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -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/vcl/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 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -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/vcl/source/gdi/svmconverter.cxx

/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.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#include <algorithm>
21#include <string.h>
22
23#include <o3tl/safeint.hxx>
24#include <osl/thread.h>
25#include <tools/fract.hxx>
26#include <tools/stream.hxx>
27#include <vcl/dibtools.hxx>
28#include <vcl/virdev.hxx>
29#include <vcl/lineinfo.hxx>
30#include <vcl/metaact.hxx>
31#include <sal/log.hxx>
32#include <osl/diagnose.h>
33
34#include <TypeSerializer.hxx>
35#include <svmconverter.hxx>
36#include <memory>
37#include <stack>
38
39// Inlines
40static void ImplReadRect( SvStream& rIStm, tools::Rectangle& rRect )
41{
42 Point aTL;
43 Point aBR;
44
45 TypeSerializer aSerializer(rIStm);
46 aSerializer.readPoint(aTL);
47 aSerializer.readPoint(aBR);
48
49 rRect = tools::Rectangle( aTL, aBR );
50}
51
52static bool ImplReadPoly(SvStream& rIStm, tools::Polygon& rPoly)
53{
54 TypeSerializer aSerializer(rIStm);
55
56 sal_Int32 nSize32(0);
57 rIStm.ReadInt32(nSize32);
58 sal_uInt16 nSize = nSize32;
59
60 const size_t nMaxPossiblePoints = rIStm.remainingSize() / 2 * sizeof(sal_Int32);
61 if (nSize > nMaxPossiblePoints)
62 {
63 SAL_WARN("vcl.gdi", "svm record claims to have: " << nSize << " points, but only " << nMaxPossiblePoints << " possible")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm record claims to have: "
<< nSize << " points, but only " << nMaxPossiblePoints
<< " possible") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "63" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "63" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm record claims to have: " << nSize <<
" points, but only " << nMaxPossiblePoints << " possible"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "63" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm record claims to have: " <<
nSize << " points, but only " << nMaxPossiblePoints
<< " possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "63" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
64 return false;
65 }
66
67 rPoly = tools::Polygon(nSize);
68
69 for (sal_uInt16 i = 0; i < nSize && rIStm.good(); ++i)
70 {
71 aSerializer.readPoint(rPoly[i]);
72 }
73 return rIStm.good();
74}
75
76static bool ImplReadPolyPoly(SvStream& rIStm, tools::PolyPolygon& rPolyPoly)
77{
78 bool bSuccess = true;
79
80 tools::Polygon aPoly;
81 sal_Int32 nPolyCount32(0);
82 rIStm.ReadInt32(nPolyCount32);
83 sal_uInt16 nPolyCount = static_cast<sal_uInt16>(nPolyCount32);
84
85 for (sal_uInt16 i = 0; i < nPolyCount && rIStm.good(); ++i)
86 {
87 if (!ImplReadPoly(rIStm, aPoly))
88 {
89 bSuccess = false;
90 break;
91 }
92 rPolyPoly.Insert(aPoly);
93 }
94
95 return bSuccess && rIStm.good();
96}
97
98static void ImplReadColor( SvStream& rIStm, Color& rColor )
99{
100 sal_Int16 nVal(0);
101
102 rIStm.ReadInt16( nVal ); rColor.SetRed( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
103 rIStm.ReadInt16( nVal ); rColor.SetGreen( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
104 rIStm.ReadInt16( nVal ); rColor.SetBlue( sal::static_int_cast<sal_uInt8>(static_cast<sal_uInt16>(nVal) >> 8) );
105}
106
107static bool ImplReadMapMode(SvStream& rIStm, MapMode& rMapMode)
108{
109 sal_Int16 nUnit(0);
110 rIStm.ReadInt16(nUnit);
111
112 Point aOrg;
113 TypeSerializer aSerializer(rIStm);
114 aSerializer.readPoint(aOrg);
115
116 sal_Int32 nXNum(0), nXDenom(0), nYNum(0), nYDenom(0);
117 rIStm.ReadInt32(nXNum).ReadInt32(nXDenom).ReadInt32(nYNum).ReadInt32(nYDenom);
118
119 if (!rIStm.good() || nXDenom <= 0 || nYDenom <= 0 || nXNum <= 0 || nYNum <= 0)
120 {
121 SAL_WARN("vcl.gdi", "Parsing error: invalid mapmode fraction")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: invalid mapmode fraction"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "121" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: invalid mapmode fraction"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Parsing error: invalid mapmode fraction"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "121" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: invalid mapmode fraction") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "121" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: invalid mapmode fraction"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Parsing error: invalid mapmode fraction"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "121" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
122 return false;
123 }
124
125 if (nUnit < sal_Int16(MapUnit::Map100thMM) || nUnit > sal_Int16(MapUnit::LAST))
126 {
127 SAL_WARN("vcl.gdi", "Parsing error: invalid mapmode")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: invalid mapmode"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "127" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: invalid mapmode"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Parsing error: invalid mapmode"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "127" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: invalid mapmode") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "127" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: invalid mapmode"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Parsing error: invalid mapmode"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "127" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
128 return false;
129 }
130
131 rMapMode = MapMode(static_cast<MapUnit>(nUnit), aOrg, Fraction(nXNum, nXDenom), Fraction(nYNum, nYDenom));
132
133 return true;
134}
135
136static void ImplReadUnicodeComment( sal_uInt32 nStrmPos, SvStream& rIStm, OUString& rString )
137{
138 sal_uInt32 nOld = rIStm.Tell();
139 if ( nStrmPos )
140 {
141 sal_uInt16 nType;
142 sal_uInt32 nActionSize;
143 std::size_t nStringLen;
144
145 rIStm.Seek( nStrmPos );
146 rIStm .ReadUInt16( nType )
147 .ReadUInt32( nActionSize );
148
149 nStringLen = (nActionSize - 4) >> 1;
150
151 if ( nStringLen && ( nType == GDI_UNICODE_COMMENT1032 ) )
152 rString = read_uInt16s_ToOUString(rIStm, nStringLen);
153 }
154 rIStm.Seek( nOld );
155}
156
157static void ImplSkipActions(SvStream& rIStm, sal_uLong nSkipCount)
158{
159 sal_Int32 nActionSize;
160 sal_Int16 nType;
161 for (sal_uLong i = 0; i < nSkipCount; ++i)
162 {
163 rIStm.ReadInt16(nType).ReadInt32(nActionSize);
164 if (!rIStm.good() || nActionSize < 4)
165 break;
166 rIStm.SeekRel(nActionSize - 4);
167 }
168}
169
170static void ImplReadExtendedPolyPolygonAction(SvStream& rIStm, tools::PolyPolygon& rPolyPoly)
171{
172 TypeSerializer aSerializer(rIStm);
173
174 rPolyPoly.Clear();
175 sal_uInt16 nPolygonCount(0);
176 rIStm.ReadUInt16( nPolygonCount );
177
178 if (!nPolygonCount)
179 return;
180
181 const size_t nMinRecordSize = sizeof(sal_uInt16);
182 const size_t nMaxRecords = rIStm.remainingSize() / nMinRecordSize;
183 if (nPolygonCount > nMaxRecords)
184 {
185 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxRecords << " max possible entries, but " << nPolygonCount
<< " claimed, truncating") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nPolygonCount
<< " claimed, truncating"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Parsing error: "
<< nMaxRecords << " max possible entries, but " <<
nPolygonCount << " claimed, truncating"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nPolygonCount << " claimed, truncating") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nPolygonCount
<< " claimed, truncating"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Parsing error: "
<< nMaxRecords << " max possible entries, but " <<
nPolygonCount << " claimed, truncating"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
186 " max possible entries, but " << nPolygonCount << " claimed, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxRecords << " max possible entries, but " << nPolygonCount
<< " claimed, truncating") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nPolygonCount
<< " claimed, truncating"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Parsing error: "
<< nMaxRecords << " max possible entries, but " <<
nPolygonCount << " claimed, truncating"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nPolygonCount << " claimed, truncating") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nPolygonCount
<< " claimed, truncating"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "Parsing error: "
<< nMaxRecords << " max possible entries, but " <<
nPolygonCount << " claimed, truncating"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "186" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
187 nPolygonCount = nMaxRecords;
188 }
189
190 for(sal_uInt16 a(0); a < nPolygonCount; a++)
191 {
192 sal_uInt16 nPointCount(0);
193 rIStm.ReadUInt16(nPointCount);
194
195 const size_t nMinPolygonSize = sizeof(sal_Int32) * 2;
196 const size_t nMaxPolygons = rIStm.remainingSize() / nMinPolygonSize;
197 if (nPointCount > nMaxPolygons)
198 {
199 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxPolygons <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxPolygons << " max possible entries, but " <<
nPointCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPolygons << " max possible entries, but "
<< nPointCount << " claimed, truncating") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
200 " max possible entries, but " << nPointCount << " claimed, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxPolygons << " max possible entries, but " <<
nPointCount << " claimed, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxPolygons << " max possible entries, but "
<< nPointCount << " claimed, truncating") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxPolygons
<< " max possible entries, but " << nPointCount <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "200" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
201 nPointCount = nMaxPolygons;
202 }
203
204 tools::Polygon aCandidate(nPointCount);
205
206 if (nPointCount)
207 {
208 for(sal_uInt16 b(0); b < nPointCount; b++)
209 {
210 aSerializer.readPoint(aCandidate[b]);
211 }
212
213 sal_uInt8 bHasFlags(int(false));
214 rIStm.ReadUChar( bHasFlags );
215
216 if(bHasFlags)
217 {
218 sal_uInt8 aPolyFlags(0);
219
220 for(sal_uInt16 c(0); c < nPointCount; c++)
221 {
222 rIStm.ReadUChar( aPolyFlags );
223 aCandidate.SetFlags(c, static_cast<PolyFlags>(aPolyFlags));
224 }
225 }
226 }
227
228 rPolyPoly.Insert(aCandidate);
229 }
230}
231
232SVMConverter::SVMConverter( SvStream& rStm, GDIMetaFile& rMtf )
233{
234 if( !rStm.GetError() )
235 {
236 ImplConvertFromSVM1( rStm, rMtf );
237 }
238}
239
240namespace
241{
242 sal_Int32 SkipActions(sal_Int32 i, sal_Int32 nFollowingActionCount, sal_Int32 nActions)
243 {
244 sal_Int32 remainingActions = nActions - i;
245 if (nFollowingActionCount < 0)
246 nFollowingActionCount = remainingActions;
247 return std::min(remainingActions, nFollowingActionCount);
248 }
249}
250
251#define LF_FACESIZE32 32
252
253void static lcl_error( SvStream& rIStm, const SvStreamEndian& nOldFormat, sal_uLong nPos)
254{
255 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
256 rIStm.SetEndian(nOldFormat);
257 rIStm.Seek(nPos);
258 return;
259}
260void SVMConverter::ImplConvertFromSVM1( SvStream& rIStm, GDIMetaFile& rMtf )
261{
262 const sal_uLong nPos = rIStm.Tell();
263 const SvStreamEndian nOldFormat = rIStm.GetEndian();
264
265 rIStm.SetEndian( SvStreamEndian::LITTLE );
266
267 char aCode[ 5 ];
268 Size aPrefSz;
269
270 // read header
271 rIStm.ReadBytes(aCode, sizeof(aCode)); // Identifier
272 sal_Int16 nSize(0);
273 rIStm.ReadInt16( nSize ); // Size
274 sal_Int16 nVersion(0);
275 rIStm.ReadInt16( nVersion ); // Version
276 sal_Int32 nTmp32(0);
277 rIStm.ReadInt32( nTmp32 );
278 if (nTmp32 < 0)
1
Assuming 'nTmp32' is >= 0
2
Taking false branch
279 {
280 SAL_WARN("vcl.gdi", "svm: value for width should be positive")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm: value for width should be positive"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "280" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: value for width should be positive"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: value for width should be positive"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "280" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm: value for width should be positive") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "280" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: value for width should be positive"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: value for width should be positive"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "280" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
281 lcl_error(rIStm, nOldFormat, nPos);
282 return;
283 }
284 aPrefSz.setWidth( nTmp32 ); // PrefSize.Width()
285 rIStm.ReadInt32( nTmp32 );
286 if (nTmp32 < 0)
3
Assuming 'nTmp32' is >= 0
4
Taking false branch
287 {
288 SAL_WARN("vcl.gdi", "svm: value for height should be positive")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm: value for height should be positive"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "288" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: value for height should be positive"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: value for height should be positive"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "288" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm: value for height should be positive") == 1)
{ ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "288" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: value for height should be positive"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: value for height should be positive"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "288" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
289 lcl_error(rIStm, nOldFormat, nPos);
290 return;
291 }
292 aPrefSz.setHeight( nTmp32 ); // PrefSize.Height()
293
294 // check header-magic and version
295 if( rIStm.GetError()
7
Taking false branch
296 || ( memcmp( aCode, "SVGDI", sizeof( aCode ) ) != 0 )
5
Assuming the condition is false
297 || ( nVersion != 200 ) )
6
Assuming 'nVersion' is equal to 200
298 {
299 SAL_WARN("vcl.gdi", "svm: wrong check for header-magic and version")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm: wrong check for header-magic and version"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "299" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: wrong check for header-magic and version"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: wrong check for header-magic and version"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"),
("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "299" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm: wrong check for header-magic and version") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "299" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm: wrong check for header-magic and version"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "svm: wrong check for header-magic and version"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"),
("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "299" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
300 lcl_error(rIStm, nOldFormat, nPos);
301 return;
302 }
303
304 LineInfo aLineInfo( LineStyle::NONE, 0 );
305 std::stack<std::unique_ptr<LineInfo>> aLIStack;
306 ScopedVclPtrInstance< VirtualDevice > aFontVDev;
8
Calling default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
10
Returning from default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
307 rtl_TextEncoding eActualCharSet = osl_getThreadTextEncoding();
308 bool bFatLine = false;
309
310 tools::Polygon aActionPoly;
311 tools::Rectangle aRect;
312 Point aPt, aPt1;
313 Size aSz;
314 Color aActionColor;
315
316 sal_uInt32 nUnicodeCommentStreamPos = 0;
317 sal_Int32 nUnicodeCommentActionNumber = 0;
318
319 rMtf.SetPrefSize(aPrefSz);
320
321 MapMode aMapMode;
322 if (ImplReadMapMode(rIStm, aMapMode)) // MapMode
11
Taking false branch
323 rMtf.SetPrefMapMode(aMapMode);
324
325 sal_Int32 nActions(0);
326 rIStm.ReadInt32(nActions); // Action count
327 if (nActions < 0)
12
Assuming 'nActions' is >= 0
13
Taking false branch
328 {
329 SAL_WARN("vcl.gdi", "svm claims negative action count (" << nActions << ")")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm claims negative action count ("
<< nActions << ")") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "329" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm claims negative action count (" <<
nActions << ")"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm claims negative action count ("
<< nActions << ")"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "329" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm claims negative action count (" << nActions
<< ")") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "329" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm claims negative action count (" <<
nActions << ")"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm claims negative action count ("
<< nActions << ")"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "329" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
330 nActions = 0;
331 }
332
333 const size_t nMinActionSize = sizeof(sal_uInt16) + sizeof(sal_Int32);
334 const size_t nMaxPossibleActions = rIStm.remainingSize() / nMinActionSize;
335 if (o3tl::make_unsigned(nActions) > nMaxPossibleActions)
14
Assuming the condition is false
15
Taking false branch
336 {
337 SAL_WARN("vcl.gdi", "svm claims more actions (" << nActions << ") than stream could provide, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm claims more actions ("
<< nActions << ") than stream could provide, truncating"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "337" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm claims more actions (" << nActions
<< ") than stream could provide, truncating"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"svm claims more actions (" << nActions << ") than stream could provide, truncating"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "337" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm claims more actions (" << nActions <<
") than stream could provide, truncating") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "337" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "svm claims more actions (" << nActions
<< ") than stream could provide, truncating"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"svm claims more actions (" << nActions << ") than stream could provide, truncating"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "337" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
338 nActions = nMaxPossibleActions;
339 }
340
341 size_t nLastPolygonAction(0);
342
343 TypeSerializer aSerializer(rIStm);
344
345 for (sal_Int32 i = 0; i < nActions && rIStm.good(); ++i)
16
Assuming 'i' is >= 'nActions'
346 {
347 sal_Int16 nType(0);
348 rIStm.ReadInt16(nType);
349 sal_Int32 nActBegin = rIStm.Tell();
350 sal_Int32 nActionSize(0);
351 rIStm.ReadInt32(nActionSize);
352
353 SAL_WARN_IF( ( nType > 33 ) && ( nType < 1024 ), "vcl.gdi", "Unknown GDIMetaAction while converting!" )do { if (true && (( nType > 33 ) && ( nType
< 1024 ))) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Unknown GDIMetaAction while converting!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "353" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Unknown GDIMetaAction while converting!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Unknown GDIMetaAction while converting!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "353" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Unknown GDIMetaAction while converting!") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "353" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Unknown GDIMetaAction while converting!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Unknown GDIMetaAction while converting!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "353" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
354
355 switch( nType )
356 {
357 case GDI_PIXEL_ACTION1:
358 {
359 aSerializer.readPoint(aPt);
360 ImplReadColor( rIStm, aActionColor );
361 rMtf.AddAction( new MetaPixelAction( aPt, aActionColor ) );
362 }
363 break;
364
365 case GDI_POINT_ACTION2:
366 {
367 aSerializer.readPoint(aPt);
368 rMtf.AddAction( new MetaPointAction( aPt ) );
369 }
370 break;
371
372 case GDI_LINE_ACTION3:
373 {
374 aSerializer.readPoint(aPt);
375 aSerializer.readPoint(aPt1);
376 rMtf.AddAction( new MetaLineAction( aPt, aPt1, aLineInfo ) );
377 }
378 break;
379
380 case GDI_LINEJOIN_ACTION1033 :
381 {
382 sal_Int16 nLineJoin(0);
383 rIStm.ReadInt16( nLineJoin );
384 aLineInfo.SetLineJoin(static_cast<basegfx::B2DLineJoin>(nLineJoin));
385 }
386 break;
387
388 case GDI_LINECAP_ACTION1036 :
389 {
390 sal_Int16 nLineCap(0);
391 rIStm.ReadInt16( nLineCap );
392 aLineInfo.SetLineCap(static_cast<css::drawing::LineCap>(nLineCap));
393 }
394 break;
395
396 case GDI_LINEDASHDOT_ACTION1035 :
397 {
398 sal_Int16 a(0);
399 sal_Int32 b(0);
400
401 rIStm.ReadInt16( a ); aLineInfo.SetDashCount(a);
402 rIStm.ReadInt32( b ); aLineInfo.SetDashLen(b);
403 rIStm.ReadInt16( a ); aLineInfo.SetDotCount(a);
404 rIStm.ReadInt32( b ); aLineInfo.SetDotLen(b);
405 rIStm.ReadInt32( b ); aLineInfo.SetDistance(b);
406
407 if(((aLineInfo.GetDashCount() && aLineInfo.GetDashLen())
408 || (aLineInfo.GetDotCount() && aLineInfo.GetDotLen()))
409 && aLineInfo.GetDistance())
410 {
411 aLineInfo.SetStyle(LineStyle::Dash);
412 }
413 }
414 break;
415
416 case GDI_EXTENDEDPOLYGON_ACTION1034 :
417 {
418 // read the tools::PolyPolygon in every case
419 tools::PolyPolygon aInputPolyPolygon;
420 ImplReadExtendedPolyPolygonAction(rIStm, aInputPolyPolygon);
421
422 // now check if it can be set somewhere
423 if(nLastPolygonAction < rMtf.GetActionSize())
424 {
425 MetaPolyLineAction* pPolyLineAction = dynamic_cast< MetaPolyLineAction* >(rMtf.GetAction(nLastPolygonAction));
426
427 if(pPolyLineAction)
428 {
429 // replace MetaPolyLineAction when we have a single polygon. Do not rely on the
430 // same point count; the originally written GDI_POLYLINE_ACTION may have been
431 // Subdivided for better quality for older usages
432 if(1 == aInputPolyPolygon.Count())
433 {
434 rMtf.ReplaceAction(
435 new MetaPolyLineAction(
436 aInputPolyPolygon.GetObject(0),
437 pPolyLineAction->GetLineInfo()),
438 nLastPolygonAction);
439 }
440 }
441 else
442 {
443 MetaPolyPolygonAction* pPolyPolygonAction = dynamic_cast< MetaPolyPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
444
445 if(pPolyPolygonAction)
446 {
447 // replace MetaPolyPolygonAction when we have a curved polygon. Do rely on the
448 // same sub-polygon count
449 if(pPolyPolygonAction->GetPolyPolygon().Count() == aInputPolyPolygon.Count())
450 {
451 rMtf.ReplaceAction(
452 new MetaPolyPolygonAction(
453 aInputPolyPolygon),
454 nLastPolygonAction);
455 }
456 }
457 else
458 {
459 MetaPolygonAction* pPolygonAction = dynamic_cast< MetaPolygonAction* >(rMtf.GetAction(nLastPolygonAction));
460
461 if(pPolygonAction)
462 {
463 // replace MetaPolygonAction
464 if(1 == aInputPolyPolygon.Count())
465 {
466 rMtf.ReplaceAction(
467 new MetaPolygonAction(
468 aInputPolyPolygon.GetObject(0)),
469 nLastPolygonAction);
470 }
471 }
472 }
473 }
474 }
475 }
476 break;
477
478 case GDI_RECT_ACTION4:
479 {
480 ImplReadRect( rIStm, aRect );
481 sal_Int32 nTmp(0), nTmp1(0);
482 rIStm.ReadInt32( nTmp ).ReadInt32( nTmp1 );
483
484 if( nTmp || nTmp1 )
485 rMtf.AddAction( new MetaRoundRectAction( aRect, nTmp, nTmp1 ) );
486 else
487 {
488 rMtf.AddAction( new MetaRectAction( aRect ) );
489
490 if( bFatLine )
491 rMtf.AddAction( new MetaPolyLineAction( aRect, aLineInfo ) );
492 }
493 }
494 break;
495
496 case GDI_ELLIPSE_ACTION5:
497 {
498 ImplReadRect( rIStm, aRect );
499
500 if( bFatLine )
501 {
502 const tools::Polygon aPoly( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
503
504 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
505 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
506 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
507 rMtf.AddAction( new MetaPopAction() );
508 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
509 }
510 else
511 rMtf.AddAction( new MetaEllipseAction( aRect ) );
512 }
513 break;
514
515 case GDI_ARC_ACTION6:
516 {
517 ImplReadRect( rIStm, aRect );
518 aSerializer.readPoint(aPt);
519 aSerializer.readPoint(aPt1);
520
521 if( bFatLine )
522 {
523 const tools::Polygon aPoly( aRect, aPt, aPt1, PolyStyle::Arc );
524
525 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
526 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
527 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
528 rMtf.AddAction( new MetaPopAction() );
529 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
530 }
531 else
532 rMtf.AddAction( new MetaArcAction( aRect, aPt, aPt1 ) );
533 }
534 break;
535
536 case GDI_PIE_ACTION7:
537 {
538 ImplReadRect( rIStm, aRect );
539 aSerializer.readPoint(aPt);
540 aSerializer.readPoint(aPt1);
541
542 if( bFatLine )
543 {
544 const tools::Polygon aPoly( aRect, aPt, aPt1, PolyStyle::Pie );
545
546 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
547 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
548 rMtf.AddAction( new MetaPolygonAction( aPoly ) );
549 rMtf.AddAction( new MetaPopAction() );
550 rMtf.AddAction( new MetaPolyLineAction( aPoly, aLineInfo ) );
551 }
552 else
553 rMtf.AddAction( new MetaPieAction( aRect, aPt, aPt1 ) );
554 }
555 break;
556
557 case GDI_INVERTRECT_ACTION8:
558 case GDI_HIGHLIGHTRECT_ACTION9:
559 {
560 ImplReadRect( rIStm, aRect );
561 rMtf.AddAction( new MetaPushAction( PushFlags::RASTEROP ) );
562 rMtf.AddAction( new MetaRasterOpAction( RasterOp::Invert ) );
563 rMtf.AddAction( new MetaRectAction( aRect ) );
564 rMtf.AddAction( new MetaPopAction() );
565 }
566 break;
567
568 case GDI_POLYLINE_ACTION10:
569 {
570 if (ImplReadPoly(rIStm, aActionPoly))
571 {
572 nLastPolygonAction = rMtf.GetActionSize();
573
574 if( bFatLine )
575 rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
576 else
577 rMtf.AddAction( new MetaPolyLineAction( aActionPoly ) );
578 }
579 }
580 break;
581
582 case GDI_POLYGON_ACTION11:
583 {
584 if (ImplReadPoly(rIStm, aActionPoly))
585 {
586 if( bFatLine )
587 {
588 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
589 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
590 rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
591 rMtf.AddAction( new MetaPopAction() );
592 rMtf.AddAction( new MetaPolyLineAction( aActionPoly, aLineInfo ) );
593 }
594 else
595 {
596 nLastPolygonAction = rMtf.GetActionSize();
597 rMtf.AddAction( new MetaPolygonAction( aActionPoly ) );
598 }
599 }
600 }
601 break;
602
603 case GDI_POLYPOLYGON_ACTION12:
604 {
605 tools::PolyPolygon aPolyPoly;
606
607 if (ImplReadPolyPoly(rIStm, aPolyPoly))
608 {
609 if( bFatLine )
610 {
611 rMtf.AddAction( new MetaPushAction( PushFlags::LINECOLOR ) );
612 rMtf.AddAction( new MetaLineColorAction( COL_TRANSPARENT, false ) );
613 rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
614 rMtf.AddAction( new MetaPopAction() );
615
616 for( sal_uInt16 nPoly = 0, nCount = aPolyPoly.Count(); nPoly < nCount; nPoly++ )
617 rMtf.AddAction( new MetaPolyLineAction( aPolyPoly[ nPoly ], aLineInfo ) );
618 }
619 else
620 {
621 nLastPolygonAction = rMtf.GetActionSize();
622 rMtf.AddAction( new MetaPolyPolygonAction( aPolyPoly ) );
623 }
624 }
625 }
626 break;
627
628 case GDI_FONT_ACTION20:
629 {
630 vcl::Font aFont;
631 char aName[LF_FACESIZE32+1];
632
633 ImplReadColor( rIStm, aActionColor ); aFont.SetColor( aActionColor );
634 ImplReadColor( rIStm, aActionColor ); aFont.SetFillColor( aActionColor );
635 size_t nRet = rIStm.ReadBytes(aName, LF_FACESIZE32);
636 aName[nRet] = 0;
637 aFont.SetFamilyName( OUString( aName, strlen(aName), rIStm.GetStreamCharSet() ) );
638
639 sal_Int32 nWidth(0), nHeight(0);
640 rIStm.ReadInt32(nWidth).ReadInt32(nHeight);
641 sal_Int16 nCharOrient(0), nLineOrient(0);
642 rIStm.ReadInt16(nCharOrient).ReadInt16(nLineOrient);
643 sal_Int16 nCharSet(0), nFamily(0), nPitch(0), nAlign(0), nWeight(0), nUnderline(0), nStrikeout(0);
644 rIStm.ReadInt16(nCharSet).ReadInt16(nFamily).ReadInt16(nPitch).ReadInt16(nAlign).ReadInt16(nWeight).ReadInt16(nUnderline).ReadInt16(nStrikeout);
645 bool bItalic(false), bOutline(false), bShadow(false), bTransparent(false);
646 rIStm.ReadCharAsBool(bItalic).ReadCharAsBool(bOutline).ReadCharAsBool(bShadow).ReadCharAsBool(bTransparent);
647
648 aFont.SetFontSize( Size( nWidth, nHeight ) );
649 aFont.SetCharSet( static_cast<rtl_TextEncoding>(nCharSet) );
650 aFont.SetFamily( static_cast<FontFamily>(nFamily) );
651 aFont.SetPitch( static_cast<FontPitch>(nPitch) );
652 aFont.SetAlignment( static_cast<FontAlignTextAlign>(nAlign) );
653 aFont.SetWeight( ( nWeight == 1 ) ? WEIGHT_LIGHT : ( nWeight == 2 ) ? WEIGHT_NORMAL :
654 ( nWeight == 3 ) ? WEIGHT_BOLD : WEIGHT_DONTKNOW );
655 aFont.SetUnderline( static_cast<FontLineStyle>(nUnderline) );
656 aFont.SetStrikeout( static_cast<FontStrikeout>(nStrikeout) );
657 aFont.SetItalic( bItalic ? ITALIC_NORMAL : ITALIC_NONE );
658 aFont.SetOutline( bOutline );
659 aFont.SetShadow( bShadow );
660 aFont.SetOrientation( nLineOrient );
661 aFont.SetTransparent( bTransparent );
662
663 eActualCharSet = aFont.GetCharSet();
664 if ( eActualCharSet == RTL_TEXTENCODING_DONTKNOW(((rtl_TextEncoding) 0)) )
665 eActualCharSet = osl_getThreadTextEncoding();
666
667 rMtf.AddAction( new MetaFontAction( aFont ) );
668 rMtf.AddAction( new MetaTextAlignAction( aFont.GetAlignment() ) );
669 rMtf.AddAction( new MetaTextColorAction( aFont.GetColor() ) );
670 rMtf.AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
671
672 // #106172# Track font relevant data in shadow VDev
673 aFontVDev->SetFont( aFont );
674 }
675 break;
676
677 case GDI_TEXT_ACTION13:
678 {
679 sal_Int32 nIndex(0), nLen(0), nTmp(0);
680 aSerializer.readPoint(aPt);
681 rIStm.ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp );
682 if (nTmp > 0)
683 {
684 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
685 sal_uInt8 nTerminator = 0;
686 rIStm.ReadUChar( nTerminator );
687 SAL_WARN_IF( nTerminator != 0, "vcl.gdi", "expected string to be NULL terminated" )do { if (true && (nTerminator != 0)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "expected string to be NULL terminated"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "687" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "687" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "expected string to be NULL terminated") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "687" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "687" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
688
689 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
690 if ( nUnicodeCommentActionNumber == i )
691 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
692 rMtf.AddAction( new MetaTextAction( aPt, aStr, nIndex, nLen ) );
693 }
694
695 if (nActionSize < 24)
696 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
697 else
698 rIStm.Seek(nActBegin + nActionSize);
699 }
700 break;
701
702 case GDI_TEXTARRAY_ACTION14:
703 {
704 sal_Int32 nIndex(0), nLen(0), nAryLen(0), nTmp(0);
705 aSerializer.readPoint(aPt);
706 rIStm.ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp ).ReadInt32( nAryLen );
707 if (nTmp > 0)
708 {
709 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
710 sal_uInt8 nTerminator = 0;
711 rIStm.ReadUChar( nTerminator );
712 SAL_WARN_IF( nTerminator != 0, "vcl.gdi", "expected string to be NULL terminated" )do { if (true && (nTerminator != 0)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "expected string to be NULL terminated"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "712" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "712" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "expected string to be NULL terminated") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "712" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "712" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
713
714 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
715
716 std::unique_ptr<long[]> pDXAry;
717 if (nAryLen > 0)
718 {
719 const size_t nMinRecordSize = sizeof(sal_Int32);
720 const size_t nMaxRecords = rIStm.remainingSize() / nMinRecordSize;
721 if (o3tl::make_unsigned(nAryLen) > nMaxRecords)
722 {
723 SAL_WARN("vcl.gdi", "Parsing error: " << nMaxRecords <<do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxRecords << " max possible entries, but " << nAryLen
<< " claimed, truncating") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nAryLen << " claimed, truncating") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
724 " max possible entries, but " << nAryLen << " claimed, truncating")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Parsing error: " <<
nMaxRecords << " max possible entries, but " << nAryLen
<< " claimed, truncating") == 1) { ::sal_detail_log( (
::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Parsing error: " << nMaxRecords << " max possible entries, but "
<< nAryLen << " claimed, truncating") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "Parsing error: " << nMaxRecords
<< " max possible entries, but " << nAryLen <<
" claimed, truncating"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "724" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
725 nAryLen = nMaxRecords;
726 }
727
728 sal_Int32 nStrLen( aStr.getLength() );
729
730 sal_Int32 nDXAryLen = std::max(nAryLen, nStrLen);
731
732 if (nDXAryLen < nLen)
733 {
734 //MetaTextArrayAction ctor expects pDXAry to be >= nLen if set, so if this can't
735 //be achieved, don't read it, it's utterly broken.
736 SAL_WARN("vcl.gdi", "dxary too short, discarding completely")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "dxary too short, discarding completely"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "736" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "dxary too short, discarding completely"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "dxary too short, discarding completely"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "736" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "dxary too short, discarding completely") == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi")
, ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "736" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "dxary too short, discarding completely"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "dxary too short, discarding completely"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "736" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
737 rIStm.SeekRel(sizeof(sal_Int32) * nDXAryLen);
738 nLen = 0;
739 nIndex = 0;
740 }
741 else
742 {
743 pDXAry.reset(new long[nDXAryLen]);
744
745 for (sal_Int32 j = 0; j < nAryLen; ++j)
746 {
747 rIStm.ReadInt32( nTmp );
748 pDXAry[ j ] = nTmp;
749 }
750
751 // #106172# Add last DX array elem, if missing
752 if( nAryLen != nStrLen )
753 {
754 if (nAryLen+1 == nStrLen && nIndex >= 0)
755 {
756 std::unique_ptr<long[]> pTmpAry(new long[nStrLen]);
757
758 aFontVDev->GetTextArray( aStr, pTmpAry.get(), nIndex, nLen );
759
760 // now, the difference between the
761 // last and the second last DX array
762 // is the advancement for the last
763 // glyph. Thus, to complete our meta
764 // action's DX array, just add that
765 // difference to last elem and store
766 // in very last.
767 if( nStrLen > 1 )
768 pDXAry[ nStrLen-1 ] = pDXAry[ nStrLen-2 ] + pTmpAry[ nStrLen-1 ] - pTmpAry[ nStrLen-2 ];
769 else
770 pDXAry[ nStrLen-1 ] = pTmpAry[ nStrLen-1 ]; // len=1: 0th position taken to be 0
771 }
772#ifdef DBG_UTIL
773 else
774 OSL_FAIL("More than one DX array element missing on SVM import")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "774" ": "), "%s", "More than one DX array element missing on SVM import"
); } } while (false)
;
775#endif
776 }
777 }
778 }
779 if ( nUnicodeCommentActionNumber == i )
780 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
781 rMtf.AddAction( new MetaTextArrayAction( aPt, aStr, pDXAry.get(), nIndex, nLen ) );
782 }
783
784 if (nActionSize < 24)
785 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
786 else
787 rIStm.Seek(nActBegin + nActionSize);
788 }
789 break;
790
791 case GDI_STRETCHTEXT_ACTION15:
792 {
793 sal_Int32 nIndex(0), nLen(0), nWidth(0), nTmp(0);
794
795 aSerializer.readPoint(aPt);
796 rIStm.ReadInt32( nIndex ).ReadInt32( nLen ).ReadInt32( nTmp ).ReadInt32( nWidth );
797 if (nTmp > 0)
798 {
799 OString aByteStr = read_uInt8s_ToOString(rIStm, nTmp);
800 sal_uInt8 nTerminator = 0;
801 rIStm.ReadUChar( nTerminator );
802 SAL_WARN_IF( nTerminator != 0, "vcl.gdi", "expected string to be NULL terminated" )do { if (true && (nTerminator != 0)) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "expected string to be NULL terminated"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "802" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "802" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "expected string to be NULL terminated") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), (
"/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "802" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "expected string to be NULL terminated"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "expected string to be NULL terminated"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "802" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
803
804 OUString aStr(OStringToOUString(aByteStr, eActualCharSet));
805 if ( nUnicodeCommentActionNumber == i )
806 ImplReadUnicodeComment( nUnicodeCommentStreamPos, rIStm, aStr );
807 rMtf.AddAction( new MetaStretchTextAction( aPt, nWidth, aStr, nIndex, nLen ) );
808 }
809
810 if (nActionSize < 28)
811 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
812 else
813 rIStm.Seek(nActBegin + nActionSize);
814 }
815 break;
816
817 case GDI_BITMAP_ACTION17:
818 {
819 Bitmap aBmp;
820
821 aSerializer.readPoint(aPt);
822 ReadDIB(aBmp, rIStm, true);
823 rMtf.AddAction( new MetaBmpAction( aPt, aBmp ) );
824 }
825 break;
826
827 case GDI_BITMAPSCALE_ACTION18:
828 {
829 Bitmap aBmp;
830
831 aSerializer.readPoint(aPt);
832 aSerializer.readSize(aSz);
833 ReadDIB(aBmp, rIStm, true);
834 rMtf.AddAction( new MetaBmpScaleAction( aPt, aSz, aBmp ) );
835 }
836 break;
837
838 case GDI_BITMAPSCALEPART_ACTION32:
839 {
840 Bitmap aBmp;
841 Size aSz2;
842
843 aSerializer.readPoint(aPt);
844 aSerializer.readSize(aSz);
845 aSerializer.readPoint(aPt1);
846 aSerializer.readSize(aSz2);
847 ReadDIB(aBmp, rIStm, true);
848 rMtf.AddAction( new MetaBmpScalePartAction( aPt, aSz, aPt1, aSz2, aBmp ) );
849 }
850 break;
851
852 case GDI_PEN_ACTION19:
853 {
854 sal_Int32 nPenWidth;
855 sal_Int16 nPenStyle;
856
857 ImplReadColor( rIStm, aActionColor );
858 rIStm.ReadInt32( nPenWidth ).ReadInt16( nPenStyle );
859
860 aLineInfo.SetStyle( nPenStyle ? LineStyle::Solid : LineStyle::NONE );
861 aLineInfo.SetWidth( nPenWidth );
862 bFatLine = nPenStyle && !aLineInfo.IsDefault();
863
864 rMtf.AddAction( new MetaLineColorAction( aActionColor, nPenStyle != 0 ) );
865 }
866 break;
867
868 case GDI_FILLBRUSH_ACTION22:
869 {
870 sal_Int16 nBrushStyle;
871
872 ImplReadColor( rIStm, aActionColor );
873 rIStm.SeekRel( 6 );
874 rIStm.ReadInt16( nBrushStyle );
875 rMtf.AddAction( new MetaFillColorAction( aActionColor, nBrushStyle != 0 ) );
876 rIStm.SeekRel( 2 );
877 }
878 break;
879
880 case GDI_MAPMODE_ACTION23:
881 {
882 if (ImplReadMapMode(rIStm, aMapMode))
883 {
884 rMtf.AddAction(new MetaMapModeAction(aMapMode));
885
886 // #106172# Track font relevant data in shadow VDev
887 aFontVDev->SetMapMode(aMapMode);
888 };
889 }
890 break;
891
892 case GDI_CLIPREGION_ACTION24:
893 {
894 vcl::Region aRegion;
895 sal_Int16 nRegType;
896 sal_Int16 bIntersect;
897 bool bClip = false;
898
899 rIStm.ReadInt16( nRegType ).ReadInt16( bIntersect );
900 ImplReadRect( rIStm, aRect );
901
902 switch( nRegType )
903 {
904 case 0:
905 break;
906
907 case 1:
908 {
909 tools::Rectangle aRegRect;
910
911 ImplReadRect( rIStm, aRegRect );
912 aRegion = vcl::Region( aRegRect );
913 bClip = true;
914 }
915 break;
916
917 case 2:
918 {
919 if (ImplReadPoly(rIStm, aActionPoly))
920 {
921 aRegion = vcl::Region( aActionPoly );
922 bClip = true;
923 }
924 }
925 break;
926
927 case 3:
928 {
929 bool bSuccess = true;
930 tools::PolyPolygon aPolyPoly;
931 sal_Int32 nPolyCount32(0);
932 rIStm.ReadInt32(nPolyCount32);
933 sal_uInt16 nPolyCount(nPolyCount32);
934
935 for (sal_uInt16 j = 0; j < nPolyCount && rIStm.good(); ++j)
936 {
937 if (!ImplReadPoly(rIStm, aActionPoly))
938 {
939 bSuccess = false;
940 break;
941 }
942 aPolyPoly.Insert(aActionPoly);
943 }
944
945 if (bSuccess)
946 {
947 aRegion = vcl::Region( aPolyPoly );
948 bClip = true;
949 }
950 }
951 break;
952 }
953
954 if( bIntersect )
955 aRegion.Intersect( aRect );
956
957 rMtf.AddAction( new MetaClipRegionAction( aRegion, bClip ) );
958 }
959 break;
960
961 case GDI_MOVECLIPREGION_ACTION28:
962 {
963 sal_Int32 nTmp(0), nTmp1(0);
964 rIStm.ReadInt32( nTmp ).ReadInt32( nTmp1 );
965 rMtf.AddAction( new MetaMoveClipRegionAction( nTmp, nTmp1 ) );
966 }
967 break;
968
969 case GDI_ISECTCLIPREGION_ACTION29:
970 {
971 ImplReadRect( rIStm, aRect );
972 rMtf.AddAction( new MetaISectRectClipRegionAction( aRect ) );
973 }
974 break;
975
976 case GDI_RASTEROP_ACTION25:
977 {
978 RasterOp eRasterOp;
979 sal_Int16 nRasterOp;
980
981 rIStm.ReadInt16( nRasterOp );
982
983 switch( nRasterOp )
984 {
985 case 1:
986 eRasterOp = RasterOp::Invert;
987 break;
988
989 case 4:
990 case 5:
991 eRasterOp = RasterOp::Xor;
992 break;
993
994 default:
995 eRasterOp = RasterOp::OverPaint;
996 break;
997 }
998
999 rMtf.AddAction( new MetaRasterOpAction( eRasterOp ) );
1000 }
1001 break;
1002
1003 case GDI_PUSH_ACTION26:
1004 {
1005 aLIStack.push(std::make_unique<LineInfo>(aLineInfo));
1006 rMtf.AddAction( new MetaPushAction( PushFlags::ALL ) );
1007
1008 // #106172# Track font relevant data in shadow VDev
1009 aFontVDev->Push();
1010 }
1011 break;
1012
1013 case GDI_POP_ACTION27:
1014 {
1015
1016 std::unique_ptr<LineInfo> xLineInfo;
1017 if (!aLIStack.empty())
1018 {
1019 xLineInfo = std::move(aLIStack.top());
1020 aLIStack.pop();
1021 }
1022
1023 // restore line info
1024 if (xLineInfo)
1025 {
1026 aLineInfo = *xLineInfo;
1027 xLineInfo.reset();
1028 bFatLine = ( LineStyle::NONE != aLineInfo.GetStyle() ) && !aLineInfo.IsDefault();
1029 }
1030
1031 rMtf.AddAction( new MetaPopAction() );
1032
1033 // #106172# Track font relevant data in shadow VDev
1034 aFontVDev->Pop();
1035 }
1036 break;
1037
1038 case GDI_GRADIENT_ACTION33:
1039 {
1040 Color aStartCol;
1041 Color aEndCol;
1042 sal_Int16 nStyle;
1043 sal_Int16 nAngle;
1044 sal_Int16 nBorder;
1045 sal_Int16 nOfsX;
1046 sal_Int16 nOfsY;
1047 sal_Int16 nIntensityStart;
1048 sal_Int16 nIntensityEnd;
1049
1050 ImplReadRect( rIStm, aRect );
1051 rIStm.ReadInt16( nStyle );
1052 ImplReadColor( rIStm, aStartCol );
1053 ImplReadColor( rIStm, aEndCol );
1054 rIStm.ReadInt16( nAngle ).ReadInt16( nBorder ).ReadInt16( nOfsX ).ReadInt16( nOfsY ).ReadInt16( nIntensityStart ).ReadInt16( nIntensityEnd );
1055
1056 Gradient aGrad( static_cast<GradientStyle>(nStyle), aStartCol, aEndCol );
1057
1058 aGrad.SetAngle( nAngle );
1059 aGrad.SetBorder( nBorder );
1060 aGrad.SetOfsX( nOfsX );
1061 aGrad.SetOfsY( nOfsY );
1062 aGrad.SetStartIntensity( nIntensityStart );
1063 aGrad.SetEndIntensity( nIntensityEnd );
1064 rMtf.AddAction( new MetaGradientAction( aRect, aGrad ) );
1065 }
1066 break;
1067
1068 case GDI_TRANSPARENT_COMMENT1024:
1069 {
1070 tools::PolyPolygon aPolyPoly;
1071 sal_Int32 nFollowingActionCount(0);
1072 sal_Int16 nTrans(0);
1073
1074 ReadPolyPolygon( rIStm, aPolyPoly );
1075 rIStm.ReadInt16( nTrans ).ReadInt32( nFollowingActionCount );
1076 ImplSkipActions( rIStm, nFollowingActionCount );
1077 rMtf.AddAction( new MetaTransparentAction( aPolyPoly, nTrans ) );
1078
1079 i = SkipActions(i, nFollowingActionCount, nActions);
1080 }
1081 break;
1082
1083 case GDI_FLOATTRANSPARENT_COMMENT1029:
1084 {
1085 GDIMetaFile aMtf;
1086 Point aPos;
1087 Size aSize;
1088 Gradient aGradient;
1089 sal_Int32 nFollowingActionCount(0);
1090
1091 ReadGDIMetaFile( rIStm, aMtf );
1092 aSerializer.readPoint(aPos);
1093 aSerializer.readSize(aSize);
1094 aSerializer.readGradient(aGradient);
1095 rIStm.ReadInt32( nFollowingActionCount );
1096 ImplSkipActions( rIStm, nFollowingActionCount );
1097 rMtf.AddAction( new MetaFloatTransparentAction( aMtf, aPos, aSize, aGradient ) );
1098
1099 i = SkipActions(i, nFollowingActionCount, nActions);
1100 }
1101 break;
1102
1103 case GDI_HATCH_COMMENT1025:
1104 {
1105 tools::PolyPolygon aPolyPoly;
1106 Hatch aHatch;
1107 sal_Int32 nFollowingActionCount(0);
1108
1109 ReadPolyPolygon( rIStm, aPolyPoly );
1110 ReadHatch( rIStm, aHatch );
1111 rIStm.ReadInt32( nFollowingActionCount );
1112 ImplSkipActions( rIStm, nFollowingActionCount );
1113 rMtf.AddAction( new MetaHatchAction( aPolyPoly, aHatch ) );
1114
1115 i = SkipActions(i, nFollowingActionCount, nActions);
1116 }
1117 break;
1118
1119 case GDI_REFPOINT_COMMENT1026:
1120 {
1121 Point aRefPoint;
1122 bool bSet;
1123 sal_Int32 nFollowingActionCount(0);
1124
1125 aSerializer.readPoint(aRefPoint);
1126 rIStm.ReadCharAsBool( bSet ).ReadInt32( nFollowingActionCount );
1127 ImplSkipActions( rIStm, nFollowingActionCount );
1128 rMtf.AddAction( new MetaRefPointAction( aRefPoint, bSet ) );
1129
1130 i = SkipActions(i, nFollowingActionCount, nActions);
1131
1132 // #106172# Track font relevant data in shadow VDev
1133 if( bSet )
1134 aFontVDev->SetRefPoint( aRefPoint );
1135 else
1136 aFontVDev->SetRefPoint();
1137 }
1138 break;
1139
1140 case GDI_TEXTLINECOLOR_COMMENT1027:
1141 {
1142 Color aColor;
1143 bool bSet;
1144 sal_Int32 nFollowingActionCount(0);
1145
1146 aSerializer.readColor(aColor);
1147 rIStm.ReadCharAsBool( bSet ).ReadInt32( nFollowingActionCount );
1148 ImplSkipActions( rIStm, nFollowingActionCount );
1149 rMtf.AddAction( new MetaTextLineColorAction( aColor, bSet ) );
1150
1151 i = SkipActions(i, nFollowingActionCount, nActions);
1152 }
1153 break;
1154
1155 case GDI_TEXTLINE_COMMENT1028:
1156 {
1157 Point aStartPt;
1158 sal_Int32 nWidth(0);
1159 sal_uInt32 nStrikeout(0);
1160 sal_uInt32 nUnderline(0);
1161 sal_Int32 nFollowingActionCount(0);
1162
1163 aSerializer.readPoint(aStartPt);
1164 rIStm.ReadInt32(nWidth ).ReadUInt32(nStrikeout).ReadUInt32(nUnderline).ReadInt32(nFollowingActionCount);
1165 ImplSkipActions(rIStm, nFollowingActionCount);
1166 rMtf.AddAction( new MetaTextLineAction( aStartPt, nWidth,
1167 static_cast<FontStrikeout>(nStrikeout),
1168 static_cast<FontLineStyle>(nUnderline),
1169 LINESTYLE_NONE ) );
1170
1171 i = SkipActions(i, nFollowingActionCount, nActions);
1172 }
1173 break;
1174
1175 case GDI_GRADIENTEX_COMMENT1030:
1176 {
1177 tools::PolyPolygon aPolyPoly;
1178 Gradient aGradient;
1179 sal_Int32 nFollowingActionCount(0);
1180
1181 ReadPolyPolygon( rIStm, aPolyPoly );
1182 aSerializer.readGradient(aGradient);
1183 rIStm.ReadInt32( nFollowingActionCount );
1184 ImplSkipActions( rIStm, nFollowingActionCount );
1185 rMtf.AddAction( new MetaGradientExAction( aPolyPoly, aGradient ) );
1186
1187 i = SkipActions(i, nFollowingActionCount, nActions);
1188 }
1189 break;
1190
1191 case GDI_COMMENT_COMMENT1031:
1192 {
1193 std::vector<sal_uInt8> aData;
1194
1195 OString aComment = read_uInt16_lenPrefixed_uInt8s_ToOString(rIStm);
1196 sal_Int32 nValue(0);
1197 sal_uInt32 nDataSize(0);
1198 rIStm.ReadInt32(nValue).ReadUInt32(nDataSize);
1199
1200 if (nDataSize)
1201 {
1202 const size_t nMaxPossibleData = rIStm.remainingSize();
1203 if (nDataSize > nMaxPossibleActions)
1204 {
1205 SAL_WARN("vcl.gdi", "svm record claims to have: " << nDataSize << " data, but only " << nMaxPossibleData << " possible")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "vcl.gdi")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "svm record claims to have: "
<< nDataSize << " data, but only " << nMaxPossibleData
<< " possible") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "1205" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "svm record claims to have: " <<
nDataSize << " data, but only " << nMaxPossibleData
<< " possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm record claims to have: " <<
nDataSize << " data, but only " << nMaxPossibleData
<< " possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "1205" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "svm record claims to have: " << nDataSize <<
" data, but only " << nMaxPossibleData << " possible"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("vcl.gdi"
), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "1205" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "svm record claims to have: " <<
nDataSize << " data, but only " << nMaxPossibleData
<< " possible"), 0); } else { ::std::ostringstream sal_detail_stream
; sal_detail_stream << "svm record claims to have: " <<
nDataSize << " data, but only " << nMaxPossibleData
<< " possible"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN
), ("vcl.gdi"), ("/home/maarten/src/libreoffice/core/vcl/source/gdi/svmconverter.cxx"
":" "1205" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1206 nDataSize = nMaxPossibleActions;
1207 }
1208 aData.resize(nDataSize);
1209 nDataSize = rIStm.ReadBytes(aData.data(), nDataSize);
1210 }
1211
1212 sal_Int32 nFollowingActionCount(0);
1213 rIStm.ReadInt32(nFollowingActionCount);
1214 ImplSkipActions( rIStm, nFollowingActionCount );
1215 rMtf.AddAction(new MetaCommentAction(aComment, nValue, aData.data(), nDataSize));
1216
1217 i = SkipActions(i, nFollowingActionCount, nActions);
1218 }
1219 break;
1220
1221 case GDI_UNICODE_COMMENT1032:
1222 {
1223 nUnicodeCommentActionNumber = i + 1;
1224 nUnicodeCommentStreamPos = rIStm.Tell() - 6;
1225 if (nActionSize < 4)
1226 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1227 else
1228 rIStm.SeekRel(nActionSize - 4);
1229 }
1230 break;
1231
1232 default:
1233 if (nActionSize < 4)
1234 rIStm.SetError(SVSTREAM_FILEFORMAT_ERRORErrCode( ErrCodeArea::Io, ErrCodeClass::Format, 21 ));
1235 else
1236 rIStm.SeekRel(nActionSize - 4);
1237 break;
1238 }
1239 }
1240
1241 rIStm.SetEndian( nOldFormat );
1242}
17
Calling implicit destructor for 'ScopedVclPtrInstance<VirtualDevice>'
18
Calling '~ScopedVclPtr'
1243
1244/* 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);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
20
Calling 'Reference::clear'
27
Returning; memory was released
205 if (aTmp.get()) {
28
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();
19
Calling 'VclPtr::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 )
9
Memory is allocated
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)
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
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
)
21
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
22
Calling 'VclReferenceBase::release'
26
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;
29
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)
23
Assuming the condition is true
24
Taking true branch
40 delete this;
25
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