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 pptx-text.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/sd/inc -I /home/maarten/src/libreoffice/core/sd/source/ui/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/oox/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -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/sd/source/filter/eppt/pptx-text.cxx

/home/maarten/src/libreoffice/core/sd/source/filter/eppt/pptx-text.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 <memory>
21#include "text.hxx"
22
23#include <com/sun/star/awt/CharSet.hpp>
24#include <com/sun/star/awt/FontWeight.hpp>
25#include <com/sun/star/awt/FontUnderline.hpp>
26#include <com/sun/star/awt/XBitmap.hpp>
27#include <com/sun/star/beans/XPropertyState.hpp>
28#include <com/sun/star/beans/XPropertySet.hpp>
29#include <com/sun/star/container/XEnumerationAccess.hpp>
30#include <com/sun/star/container/XIndexReplace.hpp>
31#include <com/sun/star/i18n/BreakIterator.hpp>
32#include <com/sun/star/i18n/ScriptDirection.hpp>
33#include <com/sun/star/i18n/ScriptType.hpp>
34#include <com/sun/star/text/FontRelief.hpp>
35#include <com/sun/star/text/XTextField.hpp>
36#include <com/sun/star/text/XTextRange.hpp>
37#include <com/sun/star/style/LineSpacing.hpp>
38#include <com/sun/star/style/LineSpacingMode.hpp>
39#include <com/sun/star/style/ParagraphAdjust.hpp>
40#include <com/sun/star/style/TabStop.hpp>
41#include <com/sun/star/graphic/XGraphic.hpp>
42
43#include <comphelper/processfactory.hxx>
44#include <editeng/svxenum.hxx>
45#include <editeng/frmdir.hxx>
46#include <filter/msfilter/util.hxx>
47#include <i18nutil/scripttypedetector.hxx>
48#include <o3tl/any.hxx>
49#include <svl/languageoptions.hxx>
50#include <osl/diagnose.h>
51#include <i18nlangtag/languagetag.hxx>
52
53#include <vcl/settings.hxx>
54#include <vcl/metric.hxx>
55#include <vcl/virdev.hxx>
56#include <vcl/svapp.hxx>
57
58using namespace css;
59
60static css::uno::Reference< css::i18n::XBreakIterator > xPPTBreakIter;
61
62PortionObj::PortionObj(const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
63 FontCollection& rFontCollection)
64 : meCharColor(css::beans::PropertyState_AMBIGUOUS_VALUE)
65 , meCharHeight(css::beans::PropertyState_AMBIGUOUS_VALUE)
66 , meFontName(css::beans::PropertyState_AMBIGUOUS_VALUE)
67 , meAsianOrComplexFont(css::beans::PropertyState_AMBIGUOUS_VALUE)
68 , meCharEscapement(css::beans::PropertyState_AMBIGUOUS_VALUE)
69 , mnCharAttrHard(0)
70 , mnCharAttr(0)
71 , mnFont(0)
72 , mnAsianOrComplexFont(0xffff)
73 , mnTextSize(0)
74 , mbLastPortion(true)
75{
76 mXPropSet = rXPropSet;
77
78 ImplGetPortionValues( rFontCollection, false );
79}
80
81PortionObj::PortionObj(css::uno::Reference< css::text::XTextRange > & rXTextRange,
82 bool bLast, FontCollection& rFontCollection)
83 : meCharColor(css::beans::PropertyState_AMBIGUOUS_VALUE)
84 , meCharHeight(css::beans::PropertyState_AMBIGUOUS_VALUE)
85 , meFontName(css::beans::PropertyState_AMBIGUOUS_VALUE)
86 , meAsianOrComplexFont(css::beans::PropertyState_AMBIGUOUS_VALUE)
87 , meCharEscapement(css::beans::PropertyState_AMBIGUOUS_VALUE)
88 , mnCharAttrHard(0)
89 , mnCharColor(0)
90 , mnCharAttr(0)
91 , mnCharHeight(0)
92 , mnFont(0)
93 , mnAsianOrComplexFont(0xffff)
94 , mnCharEscapement(0)
95 , mbLastPortion(bLast)
96{
97 OUString aString( rXTextRange->getString() );
98 OUString aURL;
99
100 mnTextSize = aString.getLength();
101 if ( bLast )
102 mnTextSize++;
103
104 if ( !mnTextSize )
105 return;
106
107 bool bRTL_endingParen = false;
108 mpFieldEntry = nullptr;
109 sal_uInt32 nFieldType = 0;
110
111 mXPropSet.set( rXTextRange, css::uno::UNO_QUERY );
112 mXPropState.set( rXTextRange, css::uno::UNO_QUERY );
113
114 bool bPropSetsValid = ( mXPropSet.is() && mXPropState.is() );
115 if ( bPropSetsValid )
116 nFieldType = ImplGetTextField( rXTextRange, mXPropSet, aURL );
117 if ( nFieldType )
118 {
119 mpFieldEntry.reset( new FieldEntry( nFieldType, 0, mnTextSize ) );
120 if ( nFieldType >> 28 == 4 )
121 {
122 mpFieldEntry->aRepresentation = aString;
123 mpFieldEntry->aFieldUrl = aURL;
124 }
125 }
126 bool bSymbol = false;
127
128 if ( bPropSetsValid && ImplGetPropertyValue( "CharFontCharSet", false ) )
129 {
130 sal_Int16 nCharset = 0;
131 mAny >>= nCharset;
132 if ( nCharset == css::awt::CharSet::SYMBOL )
133 bSymbol = true;
134 }
135 if ( mpFieldEntry && ( nFieldType & 0x800000 ) ) // placeholder ?
136 {
137 mnTextSize = 1;
138 if ( bLast )
139 mnTextSize++;
140 mpText.reset( new sal_uInt16[ mnTextSize ] );
141 mpText[ 0 ] = 0x2a;
142 }
143 else
144 {
145 // For i39516 - a closing parenthesis that ends an RTL string is displayed backwards by PPT
146 // Solution: add a Unicode Right-to-Left Mark, following the method described in i18024
147 if (bLast && !aString.isEmpty()
148 && aString[aString.getLength() - 1] == ')'
149 && FontCollection::GetScriptDirection(aString) == css::i18n::ScriptDirection::RIGHT_TO_LEFT)
150 {
151 mnTextSize++;
152 bRTL_endingParen = true;
153 }
154 mpText.reset( new sal_uInt16[ mnTextSize ] );
155 sal_uInt16 nChar;
156 for ( sal_Int32 i = 0; i < aString.getLength(); i++ )
157 {
158 nChar = static_cast<sal_uInt16>(aString[ i ]);
159 if ( nChar == 0xa )
160 nChar++;
161 else if ( !bSymbol )
162 {
163 switch ( nChar )
164 {
165 // Currency
166 case 128: nChar = 0x20AC; break;
167 // Punctuation and other
168 case 130: nChar = 0x201A; break;// SINGLE LOW-9 QUOTATION MARK
169 case 131: nChar = 0x0192; break;// LATIN SMALL LETTER F WITH HOOK
170 case 132: nChar = 0x201E; break;// DOUBLE LOW-9 QUOTATION MARK
171 // LOW DOUBLE PRIME QUOTATION MARK
172 case 133: nChar = 0x2026; break;// HORIZONTAL ELLIPSES
173 case 134: nChar = 0x2020; break;// DAGGER
174 case 135: nChar = 0x2021; break;// DOUBLE DAGGER
175 case 136: nChar = 0x02C6; break;// MODIFIER LETTER CIRCUMFLEX ACCENT
176 case 137: nChar = 0x2030; break;// PER MILLE SIGN
177 case 138: nChar = 0x0160; break;// LATIN CAPITAL LETTER S WITH CARON
178 case 139: nChar = 0x2039; break;// SINGLE LEFT-POINTING ANGLE QUOTATION MARK
179 case 140: nChar = 0x0152; break;// LATIN CAPITAL LIGATURE OE
180 case 142: nChar = 0x017D; break;// LATIN CAPITAL LETTER Z WITH CARON
181 case 145: nChar = 0x2018; break;// LEFT SINGLE QUOTATION MARK
182 // MODIFIER LETTER TURNED COMMA
183 case 146: nChar = 0x2019; break;// RIGHT SINGLE QUOTATION MARK
184 // MODIFIER LETTER APOSTROPHE
185 case 147: nChar = 0x201C; break;// LEFT DOUBLE QUOTATION MARK
186 // REVERSED DOUBLE PRIME QUOTATION MARK
187 case 148: nChar = 0x201D; break;// RIGHT DOUBLE QUOTATION MARK
188 // REVERSED DOUBLE PRIME QUOTATION MARK
189 case 149: nChar = 0x2022; break;// BULLET
190 case 150: nChar = 0x2013; break;// EN DASH
191 case 151: nChar = 0x2014; break;// EM DASH
192 case 152: nChar = 0x02DC; break;// SMALL TILDE
193 case 153: nChar = 0x2122; break;// TRADE MARK SIGN
194 case 154: nChar = 0x0161; break;// LATIN SMALL LETTER S WITH CARON
195 case 155: nChar = 0x203A; break;// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
196 case 156: nChar = 0x0153; break;// LATIN SMALL LIGATURE OE
197 case 158: nChar = 0x017E; break;// LATIN SMALL LETTER Z WITH CARON
198 case 159: nChar = 0x0178; break;// LATIN CAPITAL LETTER Y WITH DIAERESIS
199 }
200 }
201 mpText[ i ] = nChar;
202 }
203 }
204 if ( bRTL_endingParen )
205 mpText[ mnTextSize - 2 ] = 0x200F; // Unicode Right-to-Left mark
206
207 if ( bLast )
208 mpText[ mnTextSize - 1 ] = 0xd;
209
210 if ( bPropSetsValid )
211 ImplGetPortionValues( rFontCollection, true );
212}
213
214PortionObj::PortionObj( const PortionObj& rPortionObj )
215: PropStateValue( rPortionObj )
216{
217 ImplConstruct( rPortionObj );
218}
219
220PortionObj::~PortionObj()
221{
222 ImplClear();
223}
224
225void PortionObj::Write( SvStream* pStrm, bool bLast )
226{
227 sal_uInt32 nCount = mnTextSize;
228 if ( bLast && mbLastPortion )
229 nCount--;
230 for ( sal_uInt32 i = 0; i < nCount; i++ )
231 pStrm->WriteUInt16( mpText[ i ] );
232}
233
234void PortionObj::ImplGetPortionValues( FontCollection& rFontCollection, bool bGetPropStateValue )
235{
236
237 bool bOk = ImplGetPropertyValue( "CharFontName", bGetPropStateValue );
238 meFontName = ePropState;
239 if ( bOk )
240 {
241 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
242 sal_uInt32 nCount = rFontCollection.GetCount();
243 mnFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
244 if ( mnFont == nCount )
245 {
246 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
247 if ( ImplGetPropertyValue( "CharFontCharSet", false ) )
248 mAny >>= rFontDesc.CharSet;
249 if ( ImplGetPropertyValue( "CharFontFamily", false ) )
250 mAny >>= rFontDesc.Family;
251 if ( ImplGetPropertyValue( "CharFontPitch", false ) )
252 mAny >>= rFontDesc.Pitch;
253 }
254 }
255
256 sal_Int16 nScriptType = SvtLanguageOptions::FromSvtScriptTypeToI18N( SvtLanguageOptions::GetScriptTypeOfLanguage( Application::GetSettings().GetLanguageTag().getLanguageType() ) );
257 if ( mpText && mnTextSize && xPPTBreakIter.is() )
258 {
259 OUString sT( reinterpret_cast<sal_Unicode *>(mpText.get()), mnTextSize );
260 nScriptType = xPPTBreakIter->getScriptType( sT, 0 );
261 }
262 if ( nScriptType != css::i18n::ScriptType::COMPLEX )
263 {
264 bOk = ImplGetPropertyValue( "CharFontNameAsian", bGetPropStateValue );
265 meAsianOrComplexFont = ePropState;
266 if ( bOk )
267 {
268 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
269 sal_uInt32 nCount = rFontCollection.GetCount();
270 mnAsianOrComplexFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
271 if ( mnAsianOrComplexFont == nCount )
272 {
273 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
274 if ( ImplGetPropertyValue( "CharFontCharSetAsian", false ) )
275 mAny >>= rFontDesc.CharSet;
276 if ( ImplGetPropertyValue( "CharFontFamilyAsian", false ) )
277 mAny >>= rFontDesc.Family;
278 if ( ImplGetPropertyValue( "CharFontPitchAsian", false ) )
279 mAny >>= rFontDesc.Pitch;
280 }
281 }
282 }
283 else
284 {
285 bOk = ImplGetPropertyValue( "CharFontNameComplex", bGetPropStateValue );
286 meAsianOrComplexFont = ePropState;
287 if ( bOk )
288 {
289 FontCollectionEntry aFontDesc( *o3tl::doAccess<OUString>(mAny) );
290 sal_uInt32 nCount = rFontCollection.GetCount();
291 mnAsianOrComplexFont = static_cast<sal_uInt16>(rFontCollection.GetId( aFontDesc ));
292 if ( mnAsianOrComplexFont == nCount )
293 {
294 FontCollectionEntry& rFontDesc = rFontCollection.GetLast();
295 if ( ImplGetPropertyValue( "CharFontCharSetComplex", false ) )
296 mAny >>= rFontDesc.CharSet;
297 if ( ImplGetPropertyValue( "CharFontFamilyComplex", false ) )
298 mAny >>= rFontDesc.Family;
299 if ( ImplGetPropertyValue( "CharFontPitchComplex", false ) )
300 mAny >>= rFontDesc.Pitch;
301 }
302 }
303 }
304
305 OUString aCharHeightName, aCharWeightName, aCharLocaleName, aCharPostureName;
306 switch( nScriptType )
307 {
308 case css::i18n::ScriptType::ASIAN :
309 {
310 aCharHeightName = "CharHeightAsian";
311 aCharWeightName = "CharWeightAsian";
312 aCharLocaleName = "CharLocaleAsian";
313 aCharPostureName = "CharPostureAsian";
314 break;
315 }
316 case css::i18n::ScriptType::COMPLEX :
317 {
318 aCharHeightName = "CharHeightComplex";
319 aCharWeightName = "CharWeightComplex";
320 aCharLocaleName = "CharLocaleComplex";
321 aCharPostureName = "CharPostureComplex";
322 break;
323 }
324 default:
325 {
326 aCharHeightName = "CharHeight";
327 aCharWeightName = "CharWeight";
328 aCharLocaleName = "CharLocale";
329 aCharPostureName = "CharPosture";
330 break;
331 }
332 }
333
334 mnCharHeight = 24;
335 if ( GetPropertyValue( mAny, mXPropSet, aCharHeightName ) )
336 {
337 float fVal(0.0);
338 if ( mAny >>= fVal )
339 {
340 mnCharHeight = static_cast<sal_uInt16>( fVal + 0.5 );
341 meCharHeight = GetPropertyState( mXPropSet, aCharHeightName );
342 }
343 }
344 if ( GetPropertyValue( mAny, mXPropSet, aCharWeightName ) )
345 {
346 float fFloat(0.0);
347 if ( mAny >>= fFloat )
348 {
349 if ( fFloat >= css::awt::FontWeight::SEMIBOLD )
350 mnCharAttr |= 1;
351 if ( GetPropertyState( mXPropSet, aCharWeightName ) == css::beans::PropertyState_DIRECT_VALUE )
352 mnCharAttrHard |= 1;
353 }
354 }
355 if ( GetPropertyValue( mAny, mXPropSet, aCharLocaleName ) )
356 {
357 css::lang::Locale eLocale;
358 if ( mAny >>= eLocale )
359 meCharLocale = eLocale;
360 }
361 if ( GetPropertyValue( mAny, mXPropSet, aCharPostureName ) )
362 {
363 css::awt::FontSlant aFS;
364 if ( mAny >>= aFS )
365 {
366 switch( aFS )
367 {
368 case css::awt::FontSlant_OBLIQUE :
369 case css::awt::FontSlant_ITALIC :
370 mnCharAttr |= 2;
371 break;
372 default:
373 break;
374 }
375 if ( GetPropertyState( mXPropSet, aCharPostureName ) == css::beans::PropertyState_DIRECT_VALUE )
376 mnCharAttrHard |= 2;
377 }
378 }
379
380 if ( ImplGetPropertyValue( "CharUnderline", bGetPropStateValue ) )
381 {
382 sal_Int16 nVal(0);
383 mAny >>= nVal;
384 switch ( nVal )
385 {
386 case css::awt::FontUnderline::SINGLE :
387 case css::awt::FontUnderline::DOUBLE :
388 case css::awt::FontUnderline::DOTTED :
389 mnCharAttr |= 4;
390 }
391 }
392 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
393 mnCharAttrHard |= 4;
394
395 if ( ImplGetPropertyValue( "CharShadowed", bGetPropStateValue ) )
396 {
397 bool bBool(false);
398 mAny >>= bBool;
399 if ( bBool )
400 mnCharAttr |= 0x10;
401 }
402 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
403 mnCharAttrHard |= 16;
404
405 if ( ImplGetPropertyValue( "CharRelief", bGetPropStateValue ) )
406 {
407 sal_Int16 nVal(0);
408 mAny >>= nVal;
409 if ( nVal != css::text::FontRelief::NONE )
410 mnCharAttr |= 512;
411 }
412 if ( ePropState == css::beans::PropertyState_DIRECT_VALUE )
413 mnCharAttrHard |= 512;
414
415 if ( ImplGetPropertyValue( "CharColor", bGetPropStateValue ) )
416 {
417 sal_uInt32 nSOColor = *( o3tl::doAccess<sal_uInt32>(mAny) );
418 mnCharColor = nSOColor & 0xff00ff00; // green and hibyte
419 mnCharColor |= static_cast<sal_uInt8>(nSOColor) << 16; // red and blue is switched
420 mnCharColor |= static_cast<sal_uInt8>( nSOColor >> 16 );
421 }
422 meCharColor = ePropState;
423
424 mnCharEscapement = 0;
425 if ( ImplGetPropertyValue( "CharEscapement", bGetPropStateValue ) )
426 {
427 mAny >>= mnCharEscapement;
428 if ( mnCharEscapement > 100 )
429 mnCharEscapement = 33;
430 else if ( mnCharEscapement < -100 )
431 mnCharEscapement = -33;
432 }
433 meCharEscapement = ePropState;
434}
435
436void PortionObj::ImplClear()
437{
438 mpFieldEntry.reset();
439 mpText.reset();
440}
441
442void PortionObj::ImplConstruct( const PortionObj& rPortionObj )
443{
444 meCharColor = rPortionObj.meCharColor;
445 meCharHeight = rPortionObj.meCharHeight;
446 meFontName = rPortionObj.meFontName;
447 meAsianOrComplexFont = rPortionObj.meAsianOrComplexFont;
448 meCharEscapement = rPortionObj.meCharEscapement;
449 meCharLocale = rPortionObj.meCharLocale;
450 mnCharAttrHard = rPortionObj.mnCharAttrHard;
451
452 mbLastPortion = rPortionObj.mbLastPortion;
453 mnTextSize = rPortionObj.mnTextSize;
454 mnCharColor = rPortionObj.mnCharColor;
455 mnCharEscapement = rPortionObj.mnCharEscapement;
456 mnCharAttr = rPortionObj.mnCharAttr;
457 mnCharHeight = rPortionObj.mnCharHeight;
458 mnFont = rPortionObj.mnFont;
459 mnAsianOrComplexFont = rPortionObj.mnAsianOrComplexFont;
460
461 if ( rPortionObj.mpText )
462 {
463 mpText.reset( new sal_uInt16[ mnTextSize ] );
464 memcpy( mpText.get(), rPortionObj.mpText.get(), mnTextSize << 1 );
465 }
466
467 if ( rPortionObj.mpFieldEntry )
468 mpFieldEntry.reset( new FieldEntry( *( rPortionObj.mpFieldEntry ) ) );
469}
470
471sal_uInt32 PortionObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition )
472{
473 if ( mpFieldEntry && ( !mpFieldEntry->nFieldStartPos ) )
474 {
475 mpFieldEntry->nFieldStartPos += nCurrentTextPosition;
476 mpFieldEntry->nFieldEndPos += nCurrentTextPosition;
477 }
478 return mnTextSize;
479}
480
481// Return: 0 = no TextField
482// bit28->31 text field type :
483// 1 = Date
484// 2 = Time
485// 3 = SlideNumber
486// 4 = Url
487// 5 = DateTime
488// 6 = header
489// 7 = footer
490// bit24->27 text field sub type (optional)
491// 23-> PPT Textfield needs a placeholder
492
493sal_uInt32 PortionObj::ImplGetTextField( css::uno::Reference< css::text::XTextRange > & ,
494 const css::uno::Reference< css::beans::XPropertySet > & rXPropSet, OUString& rURL )
495{
496 sal_uInt32 nRetValue = 0;
497 sal_Int32 nFormat;
498 css::uno::Any aAny;
499 if ( GetPropertyValue( aAny, rXPropSet, "TextPortionType", true ) )
500 {
501 auto aTextFieldType = o3tl::doAccess<OUString>(aAny);
502 if ( *aTextFieldType == "TextField" )
503 {
504 if ( GetPropertyValue( aAny, rXPropSet, *aTextFieldType, true ) )
505 {
506 css::uno::Reference< css::text::XTextField > aXTextField;
507 if ( aAny >>= aXTextField )
508 {
509 if ( aXTextField.is() )
510 {
511 css::uno::Reference< css::beans::XPropertySet > xFieldPropSet( aXTextField, css::uno::UNO_QUERY );
512 if ( xFieldPropSet.is() )
513 {
514 OUString aFieldKind( aXTextField->getPresentation( true ) );
515 if ( aFieldKind == "Date" )
516 {
517 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
518 {
519 bool bBool = false;
520 aAny >>= bBool;
521 if ( !bBool ) // Fixed DateFields does not exist in PPT
522 {
523 if ( GetPropertyValue( aAny, xFieldPropSet, "Format", true ) )
524 {
525 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
526 switch ( nFormat )
527 {
528 default:
529 case 5 :
530 case 4 :
531 case 2 : nFormat = 0; break;
532 case 8 :
533 case 9 :
534 case 3 : nFormat = 1; break;
535 case 7 :
536 case 6 : nFormat = 2; break;
537 }
538 nRetValue |= ( ( ( 1 << 4 ) | nFormat ) << 24 ) | 0x800000;
539 }
540 }
541 }
542 }
543 else if ( aFieldKind == "URL" )
544 {
545 if ( GetPropertyValue( aAny, xFieldPropSet, "URL", true ) )
546 rURL = *o3tl::doAccess<OUString>(aAny);
547 nRetValue = 4 << 28;
548 }
549 else if ( aFieldKind == "Page" )
550 {
551 nRetValue = 3 << 28 | 0x800000;
552 }
553 else if ( aFieldKind == "Pages" )
554 {
555
556 }
557 else if ( aFieldKind == "Time" )
558 {
559 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
560 {
561 bool bBool = false;
562 aAny >>= bBool;
563 if ( !bBool )
564 {
565 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
566 {
567 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
568 nRetValue |= ( ( ( 2 << 4 ) | nFormat ) << 24 ) | 0x800000;
569 }
570 }
571 }
572 }
573 else if ( aFieldKind == "File" )
574 {
575
576 }
577 else if ( aFieldKind == "Table" )
578 {
579
580 }
581 else if ( aFieldKind == "ExtTime" )
582 {
583 if ( GetPropertyValue( aAny, xFieldPropSet, "IsFix", true ) )
584 {
585 bool bBool = false;
586 aAny >>= bBool;
587 if ( !bBool )
588 {
589 if ( GetPropertyValue( aAny, xFieldPropSet, "Format", true ) )
590 {
591 nFormat = *o3tl::doAccess<sal_Int32>(aAny);
592 switch ( nFormat )
593 {
594 default:
595 case 6 :
596 case 7 :
597 case 8 :
598 case 2 : nFormat = 12; break;
599 case 3 : nFormat = 9; break;
600 case 5 :
601 case 4 : nFormat = 10; break;
602
603 }
604 nRetValue |= ( ( ( 2 << 4 ) | nFormat ) << 24 ) | 0x800000;
605 }
606 }
607 }
608 }
609 else if ( aFieldKind == "ExtFile" )
610 {
611
612 }
613 else if ( aFieldKind == "Author" )
614 {
615
616 }
617 else if ( aFieldKind == "DateTime" )
618 {
619 nRetValue = 5 << 28 | 0x800000;
620 }
621 else if ( aFieldKind == "Header" )
622 {
623 nRetValue = 6 << 28 | 0x800000;
624 }
625 else if ( aFieldKind == "Footer" )
626 {
627 nRetValue = 7 << 28 | 0x800000;
628 }
629 }
630 }
631 }
632 }
633 }
634 }
635 return nRetValue;
636}
637
638PortionObj& PortionObj::operator=( const PortionObj& rPortionObj )
639{
640 if ( this != &rPortionObj )
641 {
642 ImplClear();
643 ImplConstruct( rPortionObj );
644 }
645 return *this;
646}
647
648ParagraphObj::ParagraphObj(const css::uno::Reference< css::beans::XPropertySet > & rXPropSet,
649 PPTExBulletProvider* pProv)
650 : PropStateValue()
651 , SOParagraph()
652 , mvPortions()
653 , mnTextSize(0)
654 , mbFirstParagraph(false)
655 , mbLastParagraph(false)
656 , mnTextAdjust(0)
657 , mnLineSpacing(0)
658 , mbFixedLineSpacing(false)
659 , mnLineSpacingTop(0)
660 , mnLineSpacingBottom(0)
661 , mbForbiddenRules(false)
662 , mbParagraphPunctation(false)
663 , mnBiDi(0)
664{
665 mXPropSet = rXPropSet;
666
667 bExtendedParameters = false;
668
669 nDepth = 0;
670 nBulletFlags = 0;
671 nParaFlags = 0;
672
673 ImplGetParagraphValues( pProv, false );
674}
675
676ParagraphObj::ParagraphObj(css::uno::Reference< css::text::XTextContent > const & rXTextContent,
677 ParaFlags aParaFlags, FontCollection& rFontCollection, PPTExBulletProvider& rProv )
678 : PropStateValue()
679 , SOParagraph()
680 , mvPortions()
681 , mnTextSize(0)
682 , mbIsBullet(false)
683 , mbFirstParagraph( aParaFlags.bFirstParagraph )
684 , mbLastParagraph( aParaFlags.bLastParagraph )
685 , meBullet(css::beans::PropertyState_AMBIGUOUS_VALUE)
686 , meTextAdjust(css::beans::PropertyState_AMBIGUOUS_VALUE)
687 , meLineSpacing(css::beans::PropertyState_AMBIGUOUS_VALUE)
688 , meLineSpacingTop(css::beans::PropertyState_AMBIGUOUS_VALUE)
689 , meLineSpacingBottom(css::beans::PropertyState_AMBIGUOUS_VALUE)
690 , meForbiddenRules(css::beans::PropertyState_AMBIGUOUS_VALUE)
691 , meParagraphPunctation(css::beans::PropertyState_AMBIGUOUS_VALUE)
692 , meBiDi(css::beans::PropertyState_AMBIGUOUS_VALUE)
693 , mnTextAdjust(0)
694 , mnLineSpacing(0)
695 , mbFixedLineSpacing(false)
696 , mnLineSpacingTop(0)
697 , mnLineSpacingBottom(0)
698 , mbForbiddenRules(false)
699 , mbParagraphPunctation(false)
700 , mnBiDi(0)
701{
702 bExtendedParameters = false;
703
704 nDepth = 0;
705 nBulletFlags = 0;
706 nParaFlags = 0;
707
708 mXPropSet.set( rXTextContent, css::uno::UNO_QUERY );
709
710 mXPropState.set( rXTextContent, css::uno::UNO_QUERY );
711
712 if ( !(mXPropSet.is() && mXPropState.is()) )
713 return;
714
715 css::uno::Reference< css::container::XEnumerationAccess > aXTextPortionEA( rXTextContent, css::uno::UNO_QUERY );
716 if ( aXTextPortionEA.is() )
717 {
718 css::uno::Reference< css::container::XEnumeration > aXTextPortionE( aXTextPortionEA->createEnumeration() );
719 if ( aXTextPortionE.is() )
720 {
721 while ( aXTextPortionE->hasMoreElements() )
722 {
723 css::uno::Reference< css::text::XTextRange > aXCursorText;
724 css::uno::Any aAny( aXTextPortionE->nextElement() );
725 if ( aAny >>= aXCursorText )
726 {
727 std::unique_ptr<PortionObj> pPortionObj(new PortionObj( aXCursorText, !aXTextPortionE->hasMoreElements(), rFontCollection ));
728 if ( pPortionObj->Count() )
729 mvPortions.push_back( std::move(pPortionObj) );
730 }
731 }
732 }
733 }
734 ImplGetParagraphValues( &rProv, true );
735}
736
737ParagraphObj::~ParagraphObj()
738{
739 ImplClear();
740}
741
742void ParagraphObj::Write( SvStream* pStrm )
743{
744 for ( std::vector<std::unique_ptr<PortionObj> >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it )
745 (*it)->Write( pStrm, mbLastParagraph );
746}
747
748void ParagraphObj::ImplClear()
749{
750 mvPortions.clear();
751}
752
753void ParagraphObj::CalculateGraphicBulletSize( sal_uInt16 nFontHeight )
754{
755 if ( ( nNumberingType != SVX_NUM_BITMAP ) || ( nBulletId == 0xffff ) )
756 return;
757
758 // calculate the bullet real size for this graphic
759 if ( aBuGraSize.Width() && aBuGraSize.Height() )
760 {
761 double fCharHeight = nFontHeight;
762 double fLen = aBuGraSize.Height();
763 fCharHeight = fCharHeight * 0.2540;
764 double fQuo = fLen / fCharHeight;
765 nBulletRealSize = static_cast<sal_Int16>( fQuo + 0.5 );
766 if ( static_cast<sal_uInt16>(nBulletRealSize) > 400 )
767 nBulletRealSize = 400;
768 }
769}
770
771void ParagraphObj::ImplGetNumberingLevel( PPTExBulletProvider* pBuProv, sal_Int16 nNumberingDepth, bool bIsBullet, bool bGetPropStateValue )
772{
773 css::uno::Any aAny;
774 if ( GetPropertyValue( aAny, mXPropSet, "ParaLeftMargin" ) )
775 {
776 sal_Int32 nVal(0);
777 if ( aAny >>= nVal )
778 nTextOfs = static_cast< sal_Int16 >( nVal / ( 2540.0 / 576 ) + 0.5 ) ;
779 }
780 if ( GetPropertyValue( aAny, mXPropSet, "ParaFirstLineIndent" ) )
781 {
782 if ( aAny >>= nBulletOfs )
783 nBulletOfs = static_cast< sal_Int32 >( nBulletOfs / ( 2540.0 / 576 ) + 0.5 );
784 }
785 if ( GetPropertyValue( aAny, mXPropSet, "NumberingIsNumber" ) )
786 aAny >>= bNumberingIsNumber;
787
788 css::uno::Reference< css::container::XIndexReplace > aXIndexReplace;
789
790 if ( bIsBullet && ImplGetPropertyValue( "NumberingRules", bGetPropStateValue ) )
791 {
792 if ( ( mAny >>= aXIndexReplace ) && nNumberingDepth < aXIndexReplace->getCount() )
793 {
794 mAny = aXIndexReplace->getByIndex( nNumberingDepth );
795 auto aPropertySequence = o3tl::doAccess<css::uno::Sequence<css::beans::PropertyValue>>(mAny);
796
797 if ( aPropertySequence->hasElements() )
798 {
799 bExtendedParameters = true;
800 nBulletRealSize = 100;
801 nMappedNumType = 0;
802
803 uno::Reference<graphic::XGraphic> xGraphic;
804 for ( const css::beans::PropertyValue& rPropValue : *aPropertySequence )
805 {
806 OUString aPropName( rPropValue.Name );
807 if ( aPropName == "NumberingType" )
808 nNumberingType = static_cast<SvxNumType>(*o3tl::doAccess<sal_Int16>(rPropValue.Value));
809 else if ( aPropName == "Adjust" )
810 nHorzAdjust = *o3tl::doAccess<sal_Int16>(rPropValue.Value);
811 else if ( aPropName == "BulletChar" )
812 {
813 OUString aString( *o3tl::doAccess<OUString>(rPropValue.Value) );
814 if ( !aString.isEmpty() )
815 cBulletId = aString[ 0 ];
816 }
817 else if ( aPropName == "BulletFont" )
818 {
819 aFontDesc = *o3tl::doAccess<css::awt::FontDescriptor>(rPropValue.Value);
820
821 // Our numbullet dialog has set the wrong textencoding for our "StarSymbol" font,
822 // instead of a Unicode encoding the encoding RTL_TEXTENCODING_SYMBOL was used.
823 // Because there might exist a lot of damaged documents I added this two lines
824 // which fixes the bullet problem for the export.
825 if ( aFontDesc.Name.equalsIgnoreAsciiCase("StarSymbol") )
826 aFontDesc.CharSet = RTL_TEXTENCODING_MS_1252(((rtl_TextEncoding) 1));
827
828 }
829 else if ( aPropName == "GraphicBitmap" )
830 {
831 auto xBitmap = rPropValue.Value.get<uno::Reference<awt::XBitmap>>();
832 xGraphic.set(xBitmap, uno::UNO_QUERY);
833 }
834 else if ( aPropName == "GraphicSize" )
835 {
836 if (auto aSize = o3tl::tryAccess<css::awt::Size>(rPropValue.Value))
837 {
838 // don't cast awt::Size to Size as on 64-bits they are not the same.
839 aBuGraSize.setWidth( aSize->Width );
840 aBuGraSize.setHeight( aSize->Height );
841 }
842 }
843 else if ( aPropName == "StartWith" )
844 nStartWith = *o3tl::doAccess<sal_Int16>(rPropValue.Value);
845 else if ( aPropName == "LeftMargin" )
846 nTextOfs = nTextOfs + static_cast< sal_Int16 >( *o3tl::doAccess<sal_Int32>(rPropValue.Value) / ( 2540.0 / 576 ) );
847 else if ( aPropName == "FirstLineOffset" )
848 nBulletOfs += static_cast<sal_Int16>( *o3tl::doAccess<sal_Int32>(rPropValue.Value) / ( 2540.0 / 576 ) );
849 else if ( aPropName == "BulletColor" )
850 {
851 sal_uInt32 nSOColor = *o3tl::doAccess<sal_uInt32>(rPropValue.Value);
852 nBulletColor = nSOColor & 0xff00ff00; // green and hibyte
853 nBulletColor |= static_cast<sal_uInt8>(nSOColor) << 16; // red
854 nBulletColor |= static_cast<sal_uInt8>( nSOColor >> 16 ) | 0xfe000000; // blue
855 }
856 else if ( aPropName == "BulletRelSize" )
857 {
858 nBulletRealSize = *o3tl::doAccess<sal_Int16>(rPropValue.Value);
859 nParaFlags |= 0x40;
860 nBulletFlags |= 8;
861 }
862 else if ( aPropName == "Prefix" )
863 sPrefix = *o3tl::doAccess<OUString>(rPropValue.Value);
864 else if ( aPropName == "Suffix" )
865 sSuffix = *o3tl::doAccess<OUString>(rPropValue.Value);
866#ifdef DBG_UTIL
867 else if ( aPropName != "SymbolTextDistance" && aPropName != "GraphicBitmap" )
868 {
869 OSL_FAIL( "Unknown Property" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sd/source/filter/eppt/pptx-text.cxx"
":" "869" ": "), "%s", "Unknown Property"); } } while (false
)
;
870 }
871#endif
872 }
873
874 if (xGraphic.is())
875 {
876 if ( aBuGraSize.Width() && aBuGraSize.Height() )
877 {
878 nBulletId = pBuProv->GetId(xGraphic, aBuGraSize );
879 if ( nBulletId != 0xffff )
880 bExtendedBulletsUsed = true;
881 }
882 else
883 {
884 nNumberingType = SVX_NUM_NUMBER_NONE;
885 }
886 }
887
888 CalculateGraphicBulletSize( ( mvPortions.empty() ) ? 24 : mvPortions.front()->mnCharHeight );
889
890 switch( nNumberingType )
891 {
892 case SVX_NUM_NUMBER_NONE : nParaFlags |= 0xf; break;
893
894 case SVX_NUM_CHAR_SPECIAL : // Bullet
895 {
896 if ( IsStarSymbol(aFontDesc.Name) )
897 {
898 rtl_TextEncoding eChrSet = aFontDesc.CharSet;
899 cBulletId = msfilter::util::bestFitOpenSymbolToMSFont(cBulletId, eChrSet, aFontDesc.Name);
900 aFontDesc.CharSet = eChrSet;
901 }
902
903 if ( !aFontDesc.Name.isEmpty() )
904 {
905 nParaFlags |= 0x90; // we define the font and charset
906 }
907
908 [[fallthrough]];
909 }
910 case SVX_NUM_CHARS_UPPER_LETTER : // count from a-z, aa - az, ba - bz, ...
911 case SVX_NUM_CHARS_LOWER_LETTER :
912 case SVX_NUM_ROMAN_UPPER :
913 case SVX_NUM_ROMAN_LOWER :
914 case SVX_NUM_ARABIC :
915 case SVX_NUM_PAGEDESC : // numbering from the page template
916 case SVX_NUM_BITMAP :
917 case SVX_NUM_CHARS_UPPER_LETTER_N : // count from a-z, aa-zz, aaa-zzz
918 case SVX_NUM_CHARS_LOWER_LETTER_N :
919 case SVX_NUM_NUMBER_UPPER_ZH:
920 case SVX_NUM_CIRCLE_NUMBER:
921 case SVX_NUM_NUMBER_UPPER_ZH_TW:
922 case SVX_NUM_NUMBER_LOWER_ZH:
923 case SVX_NUM_FULL_WIDTH_ARABIC:
924 {
925 if ( nNumberingType != SVX_NUM_CHAR_SPECIAL )
926 {
927 bExtendedBulletsUsed = true;
928 if ( nNumberingDepth & 1 )
929 cBulletId = 0x2013; // defaulting bullet characters for ppt97
930 else if ( nNumberingDepth == 4 )
931 cBulletId = 0xbb;
932 else
933 cBulletId = 0x2022;
934
935 switch( nNumberingType )
936 {
937 case SVX_NUM_CHARS_UPPER_LETTER :
938 case SVX_NUM_CHARS_UPPER_LETTER_N :
939 {
940 if ( sSuffix == ")" )
941 {
942 if ( sPrefix == "(" )
943 nMappedNumType = 0xa0001; // (A)
944 else
945 nMappedNumType = 0xb0001; // A)
946 }
947 else
948 nMappedNumType = 0x10001; // A.
949 }
950 break;
951 case SVX_NUM_CHARS_LOWER_LETTER :
952 case SVX_NUM_CHARS_LOWER_LETTER_N :
953 {
954 if ( sSuffix == ")" )
955 {
956 if ( sPrefix == "(" )
957 nMappedNumType = 0x80001; // (a)
958 else
959 nMappedNumType = 0x90001; // a)
960 }
961 else
962 nMappedNumType = 0x00001; // a.
963 }
964 break;
965 case SVX_NUM_ROMAN_UPPER :
966 {
967 if ( sSuffix == ")" )
968 {
969 if ( sPrefix == "(" )
970 nMappedNumType = 0xe0001; // (I)
971 else
972 nMappedNumType = 0xf0001; // I)
973 }
974 else
975 nMappedNumType = 0x70001; // I.
976 }
977 break;
978 case SVX_NUM_ROMAN_LOWER :
979 {
980 if ( sSuffix == ")" )
981 {
982 if ( sPrefix == "(" )
983 nMappedNumType = 0x40001; // (i)
984 else
985 nMappedNumType = 0x50001; // i)
986 }
987 else
988 nMappedNumType = 0x60001; // i.
989 }
990 break;
991 case SVX_NUM_ARABIC :
992 {
993 if ( sSuffix == ")" )
994 {
995 if ( sPrefix == "(" )
996 nMappedNumType = 0xc0001; // (1)
997 else
998 nMappedNumType = 0x20001; // 1)
999 }
1000 else
1001 {
1002 if ( sSuffix.isEmpty() && sPrefix.isEmpty() )
1003 nMappedNumType = 0xd0001; // 1
1004 else
1005 nMappedNumType = 0x30001; // 1.
1006 }
1007 }
1008 break;
1009 case SVX_NUM_NUMBER_UPPER_ZH :
1010 {
1011 if ( !sSuffix.isEmpty() )
1012 nMappedNumType = 0x110001; // Simplified Chinese with single-byte period.
1013 else
1014 nMappedNumType = 0x100001; // Simplified Chinese.
1015 }
1016 break;
1017 case SVX_NUM_CIRCLE_NUMBER :
1018 {
1019 nMappedNumType = 0x120001; // Double byte circle numbers.
1020 }
1021 break;
1022 case SVX_NUM_NUMBER_UPPER_ZH_TW :
1023 {
1024 if ( !sSuffix.isEmpty() )
1025 nMappedNumType = 0x160001; // Traditional Chinese with single-byte period.
1026 else
1027 nMappedNumType = 0x150001; // Traditional Chinese.
1028 }
1029 break;
1030 case SVX_NUM_NUMBER_LOWER_ZH :
1031 {
1032 if ( sSuffix == u"\uff0e" )
1033 nMappedNumType = 0x260001; // Japanese with double-byte period.
1034 else if ( !sSuffix.isEmpty() )
1035 nMappedNumType = 0x1B0001; // Japanese/Korean with single-byte period.
1036 else
1037 nMappedNumType = 0x1A0001; // Japanese/Korean.
1038 }
1039 break;
1040 case SVX_NUM_FULL_WIDTH_ARABIC :
1041 {
1042 if ( !sSuffix.isEmpty() )
1043 nMappedNumType = 0x1D0001; // Double-byte Arabic numbers with double-byte period.
1044 else
1045 nMappedNumType = 0x1C0001; // Double-byte Arabic numbers.
1046 }
1047 break;
1048 default:
1049 break;
1050 }
1051 }
1052 nParaFlags |= 0x2f;
1053 nBulletFlags |= 6;
1054 if ( mbIsBullet && bNumberingIsNumber )
1055 nBulletFlags |= 1;
1056 break;
1057 }
1058 default:
1059 break;
1060 }
1061 }
1062 }
1063 }
1064 nBulletOfs = nTextOfs + nBulletOfs;
1065 if ( nBulletOfs < 0 )
1066 nBulletOfs = 0;
1067}
1068
1069void ParagraphObj::ImplGetParagraphValues( PPTExBulletProvider* pBuProv, bool bGetPropStateValue )
1070{
1071 css::uno::Any aAny;
1072 if ( GetPropertyValue( aAny, mXPropSet, "NumberingLevel", true ) )
1073 {
1074 if ( bGetPropStateValue )
1075 meBullet = GetPropertyState( mXPropSet, "NumberingLevel" );
1076 nDepth = *o3tl::doAccess<sal_Int16>(aAny);
1077
1078 if ( nDepth < 0 )
1079 {
1080 mbIsBullet = false;
1081 nDepth = 0;
1082 }
1083 else
1084 {
1085 if ( nDepth > 4 )
1086 nDepth = 4;
1087 mbIsBullet = true;
1088 }
1089 }
1090 else
1091 {
1092 nDepth = 0;
1093 mbIsBullet = false;
1094 }
1095 ImplGetNumberingLevel( pBuProv, nDepth, mbIsBullet, bGetPropStateValue );
1096
1097 if ( ImplGetPropertyValue( "ParaTabStops", bGetPropStateValue ) )
1098 maTabStop = *o3tl::doAccess<css::uno::Sequence<css::style::TabStop>>(mAny);
1099 sal_Int16 eTextAdjust = sal_Int16(css::style::ParagraphAdjust_LEFT);
1100 if ( GetPropertyValue( aAny, mXPropSet, "ParaAdjust", bGetPropStateValue ) )
1101 aAny >>= eTextAdjust;
1102 switch ( static_cast<css::style::ParagraphAdjust>(eTextAdjust) )
1103 {
1104 case css::style::ParagraphAdjust_CENTER :
1105 mnTextAdjust = 1;
1106 break;
1107 case css::style::ParagraphAdjust_RIGHT :
1108 mnTextAdjust = 2;
1109 break;
1110 case css::style::ParagraphAdjust_BLOCK :
1111 mnTextAdjust = 3;
1112 break;
1113 default :
1114 case css::style::ParagraphAdjust_LEFT :
1115 mnTextAdjust = 0;
1116 break;
1117 }
1118 meTextAdjust = ePropState;
1119
1120 if ( ImplGetPropertyValue( "ParaLineSpacing", bGetPropStateValue ) )
1121 {
1122 css::style::LineSpacing aLineSpacing
1123 = *o3tl::doAccess<css::style::LineSpacing>(mAny);
1124 switch ( aLineSpacing.Mode )
1125 {
1126 case css::style::LineSpacingMode::FIX :
1127 mnLineSpacing = static_cast<sal_Int16>(-( aLineSpacing.Height ) );
1128 mbFixedLineSpacing = true;
1129 break;
1130 case css::style::LineSpacingMode::MINIMUM :
1131 case css::style::LineSpacingMode::LEADING :
1132 mnLineSpacing = static_cast<sal_Int16>(-( aLineSpacing.Height ) );
1133 mbFixedLineSpacing = false;
1134 break;
1135
1136 case css::style::LineSpacingMode::PROP :
1137 default:
1138 mnLineSpacing = aLineSpacing.Height;
1139 break;
1140 }
1141 }
1142 meLineSpacing = ePropState;
1143
1144 if ( ImplGetPropertyValue( "ParaBottomMargin", bGetPropStateValue ) )
1145 {
1146 double fSpacing = *o3tl::doAccess<sal_uInt32>(mAny) + ( 2540.0 / 576.0 ) - 1;
1147 mnLineSpacingBottom = static_cast<sal_Int16>(-( fSpacing * 576.0 / 2540.0 ) );
1148 }
1149 meLineSpacingBottom = ePropState;
1150
1151 if ( ImplGetPropertyValue( "ParaTopMargin", bGetPropStateValue ) )
1152 {
1153 double fSpacing = *o3tl::doAccess<sal_uInt32>(mAny) + ( 2540.0 / 576.0 ) - 1;
1154 mnLineSpacingTop = static_cast<sal_Int16>(-( fSpacing * 576.0 / 2540.0 ) );
1155 }
1156 meLineSpacingTop = ePropState;
1157
1158 if ( ImplGetPropertyValue( "ParaIsForbiddenRules", bGetPropStateValue ) )
1159 mAny >>= mbForbiddenRules;
1160 meForbiddenRules = ePropState;
1161
1162 if ( ImplGetPropertyValue( "ParaIsHangingPunctuation", bGetPropStateValue ) )
1163 mAny >>= mbParagraphPunctation;
1164 meParagraphPunctation = ePropState;
1165
1166 mnBiDi = 0;
1167 if ( ImplGetPropertyValue( "WritingMode", bGetPropStateValue ) )
1168 {
1169 sal_Int16 nWritingMode = 0;
1170 mAny >>= nWritingMode;
1171
1172 SvxFrameDirection eWritingMode = static_cast<SvxFrameDirection>(nWritingMode);
1173 if ( ( eWritingMode == SvxFrameDirection::Horizontal_RL_TB )
1174 || ( eWritingMode == SvxFrameDirection::Vertical_RL_TB ) )
1175 {
1176 mnBiDi = 1;
1177 }
1178 }
1179 meBiDi = ePropState;
1180}
1181
1182void ParagraphObj::ImplConstruct( const ParagraphObj& rParagraphObj )
1183{
1184 mbIsBullet = rParagraphObj.mbIsBullet;
1185 meBullet = rParagraphObj.meBullet;
1186 meTextAdjust = rParagraphObj.meTextAdjust;
1187 meLineSpacing = rParagraphObj.meLineSpacing;
1188 meLineSpacingTop = rParagraphObj.meLineSpacingTop;
1189 meLineSpacingBottom = rParagraphObj.meLineSpacingBottom;
1190 meForbiddenRules = rParagraphObj.meForbiddenRules;
1191 meParagraphPunctation = rParagraphObj.meParagraphPunctation;
1192 meBiDi =rParagraphObj.meBiDi;
1193 mbFixedLineSpacing = rParagraphObj.mbFixedLineSpacing;
1194 mnTextSize = rParagraphObj.mnTextSize;
1195 mnTextAdjust = rParagraphObj.mnTextAdjust;
1196 mnLineSpacing = rParagraphObj.mnLineSpacing;
1197 mnLineSpacingTop = rParagraphObj.mnLineSpacingTop;
1198 mnLineSpacingBottom = rParagraphObj.mnLineSpacingBottom;
1199 mbFirstParagraph = rParagraphObj.mbFirstParagraph;
1200 mbLastParagraph = rParagraphObj.mbLastParagraph;
1201 mbParagraphPunctation = rParagraphObj.mbParagraphPunctation;
1202 mbForbiddenRules = rParagraphObj.mbForbiddenRules;
1203 mnBiDi = rParagraphObj.mnBiDi;
1204
1205 for ( std::vector<std::unique_ptr<PortionObj> >::const_iterator it = rParagraphObj.begin(); it != rParagraphObj.end(); ++it )
1206 mvPortions.push_back( std::make_unique<PortionObj>( **it ) );
1207
1208 maTabStop = rParagraphObj.maTabStop;
1209 bExtendedParameters = rParagraphObj.bExtendedParameters;
1210 nParaFlags = rParagraphObj.nParaFlags;
1211 nBulletFlags = rParagraphObj.nBulletFlags;
1212 sPrefix = rParagraphObj.sPrefix;
1213 sSuffix = rParagraphObj.sSuffix;
1214 sGraphicUrl = rParagraphObj.sGraphicUrl; // String to a graphic
1215 aBuGraSize = rParagraphObj.aBuGraSize;
1216 nNumberingType = rParagraphObj.nNumberingType; // this is actually a SvxEnum
1217 nHorzAdjust = rParagraphObj.nHorzAdjust;
1218 nBulletColor = rParagraphObj.nBulletColor;
1219 nBulletOfs = rParagraphObj.nBulletOfs;
1220 nStartWith = rParagraphObj.nStartWith; // start of numbering
1221 nTextOfs = rParagraphObj.nTextOfs;
1222 nBulletRealSize = rParagraphObj.nBulletRealSize; // scale in percent
1223 nDepth = rParagraphObj.nDepth; // actual depth
1224 cBulletId = rParagraphObj.cBulletId; // if Numbering Type == CharSpecial
1225 aFontDesc = rParagraphObj.aFontDesc;
1226
1227 bExtendedBulletsUsed = rParagraphObj.bExtendedBulletsUsed;
1228 nBulletId = rParagraphObj.nBulletId;
1229}
1230
1231sal_uInt32 ParagraphObj::ImplCalculateTextPositions( sal_uInt32 nCurrentTextPosition )
1232{
1233 mnTextSize = 0;
1234 for ( std::vector<std::unique_ptr<PortionObj> >::iterator it = mvPortions.begin(); it != mvPortions.end(); ++it )
1235 mnTextSize += (*it)->ImplCalculateTextPositions( nCurrentTextPosition + mnTextSize );
1236 return mnTextSize;
1237}
1238
1239ParagraphObj& ParagraphObj::operator=( const ParagraphObj& rParagraphObj )
1240{
1241 if ( this != &rParagraphObj )
1242 {
1243 ImplClear();
1244 ImplConstruct( rParagraphObj );
1245 }
1246 return *this;
1247}
1248
1249struct ImplTextObj
1250{
1251 sal_uInt32 mnTextSize;
1252 int mnInstance;
1253 std::vector<std::unique_ptr<ParagraphObj>> maList;
1254 bool mbHasExtendedBullets;
1255
1256 explicit ImplTextObj( int nInstance );
1257};
1258
1259ImplTextObj::ImplTextObj( int nInstance )
1260 : mnTextSize(0),
1261 mnInstance(nInstance),
1262 maList(),
1263 mbHasExtendedBullets(false)
1264{
1265}
1266
1267TextObj::TextObj( css::uno::Reference< css::text::XSimpleText > const & rXTextRef,
1268 int nInstance, FontCollection& rFontCollection, PPTExBulletProvider& rProv ):
1269 mpImplTextObj(std::make_shared<ImplTextObj>(nInstance))
1270{
1271 css::uno::Reference< css::container::XEnumerationAccess > aXTextParagraphEA( rXTextRef, css::uno::UNO_QUERY );
1272
1273 if ( aXTextParagraphEA.is() )
1274 {
1275 css::uno::Reference< css::container::XEnumeration > aXTextParagraphE( aXTextParagraphEA->createEnumeration() );
1276 if ( aXTextParagraphE.is() )
1277 {
1278 ParaFlags aParaFlags;
1279 while ( aXTextParagraphE->hasMoreElements() )
1280 {
1281 css::uno::Reference< css::text::XTextContent > aXParagraph;
1282 css::uno::Any aAny( aXTextParagraphE->nextElement() );
1283 if ( aAny >>= aXParagraph )
1284 {
1285 if ( !aXTextParagraphE->hasMoreElements() )
1286 aParaFlags.bLastParagraph = true;
1287 std::unique_ptr<ParagraphObj> pPara(new ParagraphObj( aXParagraph, aParaFlags, rFontCollection, rProv ));
1288 mpImplTextObj->mbHasExtendedBullets |= pPara->bExtendedBulletsUsed;
1289 mpImplTextObj->maList.push_back( std::move(pPara) );
1290 aParaFlags.bFirstParagraph = false;
1291 }
1292 }
1293 }
1294 }
1295 ImplCalculateTextPositions();
1296}
1297
1298void TextObj::ImplCalculateTextPositions()
1299{
1300 mpImplTextObj->mnTextSize = 0;
1301 for ( sal_uInt32 i = 0; i < ParagraphCount(); ++i )
1302 mpImplTextObj->mnTextSize += GetParagraph(i)->ImplCalculateTextPositions( mpImplTextObj->mnTextSize );
1303}
1304
1305ParagraphObj* TextObj::GetParagraph(int idx)
1306{
1307 return mpImplTextObj->maList[idx].get();
1308}
1309
1310sal_uInt32 TextObj::ParagraphCount() const
1311{
1312 return mpImplTextObj->maList.size();
1313}
1314
1315sal_uInt32 TextObj::Count() const
1316{
1317 return mpImplTextObj->mnTextSize;
1318}
1319
1320int TextObj::GetInstance() const
1321{
1322 return mpImplTextObj->mnInstance;
1323}
1324
1325bool TextObj::HasExtendedBullets() const
1326{
1327 return mpImplTextObj->mbHasExtendedBullets;
1328}
1329
1330void FontCollectionEntry::ImplInit( const OUString& rName )
1331{
1332 OUString aSubstName( GetSubsFontName( rName, SubsFontFlags::ONLYONE | SubsFontFlags::MS ) );
1333 if ( !aSubstName.isEmpty() )
1334 {
1335 Name = aSubstName;
1336 }
1337 else
1338 {
1339 Name = rName;
1340 }
1341}
1342
1343FontCollection::~FontCollection()
1344{
1345 pVDev.disposeAndClear();
1
Calling 'VclPtr::disposeAndClear'
1346 xPPTBreakIter = nullptr;
1347}
1348
1349FontCollection::FontCollection() :
1350 pVDev ( nullptr )
1351{
1352 xPPTBreakIter = css::i18n::BreakIterator::create( ::comphelper::getProcessComponentContext() );
1353}
1354
1355short FontCollection::GetScriptDirection( const OUString& rString )
1356{
1357 short nRet = ScriptTypeDetector::getScriptDirection( rString, 0, css::i18n::ScriptDirection::NEUTRAL );
1358 return nRet;
1359}
1360
1361sal_uInt32 FontCollection::GetId( FontCollectionEntry& rEntry )
1362{
1363 if( !rEntry.Name.isEmpty() )
1364 {
1365 const sal_uInt32 nFonts = maFonts.size();
1366
1367 for( sal_uInt32 i = 0; i < nFonts; i++ )
1368 {
1369 const FontCollectionEntry* pEntry = GetById( i );
1370 if( pEntry->Name == rEntry.Name )
1371 return i;
1372 }
1373 vcl::Font aFont;
1374 aFont.SetCharSet( rEntry.CharSet );
1375 aFont.SetFamilyName( rEntry.Original );
1376 aFont.SetFontHeight( 100 );
1377
1378 if ( !pVDev )
1379 pVDev = VclPtr<VirtualDevice>::Create();
1380
1381 pVDev->SetFont( aFont );
1382 FontMetric aMetric( pVDev->GetFontMetric() );
1383
1384 sal_uInt16 nTxtHeight = static_cast<sal_uInt16>(aMetric.GetAscent()) + static_cast<sal_uInt16>(aMetric.GetDescent());
1385
1386 if ( nTxtHeight )
1387 {
1388 double fScaling = static_cast<double>(nTxtHeight) / 120.0;
1389 if ( ( fScaling > 0.50 ) && ( fScaling < 1.5 ) )
1390 rEntry.Scaling = fScaling;
1391 }
1392
1393 maFonts.push_back(rEntry);
1394 return nFonts;
1395 }
1396 return 0;
1397}
1398
1399const FontCollectionEntry* FontCollection::GetById( sal_uInt32 nId )
1400{
1401 return nId < maFonts.size() ? &maFonts[nId] : nullptr;
1402}
1403
1404/* 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);
2
Calling copy constructor for 'Reference<VirtualDevice>'
5
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
6
Calling 'Reference::clear'
13
Returning; memory was released
205 if (aTmp.get()) {
14
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
3
Assuming field 'm_pBody' is non-null
4
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
6.1
Field 'm_pBody' is non-null
)
7
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
8
Calling 'VclReferenceBase::release'
12
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;
15
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)
9
Assuming the condition is true
10
Taking true branch
40 delete this;
11
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