File: | home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx |
Warning: | line 591, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 <vcl/metric.hxx> | |||
21 | #include <vcl/outdev.hxx> | |||
22 | #include <vcl/print.hxx> | |||
23 | #include <tools/debug.hxx> | |||
24 | #include <tools/gen.hxx> | |||
25 | #include <tools/poly.hxx> | |||
26 | #include <unotools/charclass.hxx> | |||
27 | #include <com/sun/star/i18n/KCharacterType.hpp> | |||
28 | #include <editeng/svxfont.hxx> | |||
29 | #include <editeng/escapementitem.hxx> | |||
30 | #include <sal/log.hxx> | |||
31 | ||||
32 | SvxFont::SvxFont() | |||
33 | { | |||
34 | nKern = nEsc = 0; | |||
35 | nPropr = 100; | |||
36 | eCaseMap = SvxCaseMap::NotMapped; | |||
37 | SetLanguage(LANGUAGE_SYSTEMLanguageType(0x0000)); | |||
38 | } | |||
39 | ||||
40 | SvxFont::SvxFont( const vcl::Font &rFont ) | |||
41 | : Font( rFont ) | |||
42 | { | |||
43 | nKern = nEsc = 0; | |||
44 | nPropr = 100; | |||
45 | eCaseMap = SvxCaseMap::NotMapped; | |||
46 | SetLanguage(LANGUAGE_SYSTEMLanguageType(0x0000)); | |||
47 | } | |||
48 | ||||
49 | SvxFont::SvxFont( const SvxFont &rFont ) | |||
50 | : Font( rFont ) | |||
51 | { | |||
52 | nKern = rFont.GetFixKerning(); | |||
53 | nEsc = rFont.GetEscapement(); | |||
54 | nPropr = rFont.GetPropr(); | |||
55 | eCaseMap = rFont.GetCaseMap(); | |||
56 | SetLanguage(rFont.GetLanguage()); | |||
57 | } | |||
58 | ||||
59 | void SvxFont::SetNonAutoEscapement(short nNewEsc, const OutputDevice* pOutDev) | |||
60 | { | |||
61 | nEsc = nNewEsc; | |||
62 | if ( abs(nEsc) == DFLT_ESC_AUTO_SUPER(13999 +1) ) | |||
63 | { | |||
64 | double fAutoAscent = .8; | |||
65 | double fAutoDescent = .2; | |||
66 | if ( pOutDev ) | |||
67 | { | |||
68 | const FontMetric& rFontMetric = pOutDev->GetFontMetric(); | |||
69 | double fFontHeight = rFontMetric.GetAscent() + rFontMetric.GetDescent(); | |||
70 | if ( fFontHeight ) | |||
71 | { | |||
72 | fAutoAscent = rFontMetric.GetAscent() / fFontHeight; | |||
73 | fAutoDescent = rFontMetric.GetDescent() / fFontHeight; | |||
74 | } | |||
75 | } | |||
76 | ||||
77 | if ( nEsc == DFLT_ESC_AUTO_SUPER(13999 +1) ) | |||
78 | nEsc = fAutoAscent * (100 - nPropr); | |||
79 | else //DFLT_ESC_AUTO_SUB | |||
80 | nEsc = fAutoDescent * -(100 - nPropr); | |||
81 | } | |||
82 | ||||
83 | if ( nEsc > MAX_ESC_POS13999 ) | |||
84 | nEsc = MAX_ESC_POS13999; | |||
85 | else if ( nEsc < -MAX_ESC_POS13999 ) | |||
86 | nEsc = -MAX_ESC_POS13999; | |||
87 | } | |||
88 | ||||
89 | void SvxFont::DrawArrow( OutputDevice &rOut, const tools::Rectangle& rRect, | |||
90 | const Size& rSize, const Color& rCol, bool bLeft ) | |||
91 | { | |||
92 | long nLeft = ( rRect.Left() + rRect.Right() - rSize.Width() )/ 2; | |||
93 | long nRight = nLeft + rSize.Width(); | |||
94 | long nMid = ( rRect.Top() + rRect.Bottom() ) / 2; | |||
95 | long nTop = nMid - rSize.Height() / 2; | |||
96 | long nBottom = nTop + rSize.Height(); | |||
97 | if( nLeft < rRect.Left() ) | |||
98 | { | |||
99 | nLeft = rRect.Left(); | |||
100 | nRight = rRect.Right(); | |||
101 | } | |||
102 | if( nTop < rRect.Top() ) | |||
103 | { | |||
104 | nTop = rRect.Top(); | |||
105 | nBottom = rRect.Bottom(); | |||
106 | } | |||
107 | tools::Polygon aPoly; | |||
108 | Point aTmp( bLeft ? nLeft : nRight, nMid ); | |||
109 | Point aNxt( bLeft ? nRight : nLeft, nTop ); | |||
110 | aPoly.Insert( 0, aTmp ); | |||
111 | aPoly.Insert( 0, aNxt ); | |||
112 | aNxt.setY( nBottom ); | |||
113 | aPoly.Insert( 0, aNxt ); | |||
114 | aPoly.Insert( 0, aTmp ); | |||
115 | Color aOldLineColor = rOut.GetLineColor(); | |||
116 | Color aOldFillColor = rOut.GetFillColor(); | |||
117 | rOut.SetFillColor( rCol ); | |||
118 | rOut.SetLineColor( COL_BLACK ); | |||
119 | rOut.DrawPolygon( aPoly ); | |||
120 | rOut.DrawLine( aTmp, aNxt ); | |||
121 | rOut.SetLineColor( aOldLineColor ); | |||
122 | rOut.SetFillColor( aOldFillColor ); | |||
123 | } | |||
124 | ||||
125 | ||||
126 | OUString SvxFont::CalcCaseMap(const OUString &rTxt) const | |||
127 | { | |||
128 | if (!IsCaseMap() || rTxt.isEmpty()) | |||
129 | return rTxt; | |||
130 | OUString aTxt(rTxt); | |||
131 | // I still have to get the language | |||
132 | const LanguageType eLang = LANGUAGE_DONTKNOWLanguageType(0x03FF) == GetLanguage() | |||
133 | ? LANGUAGE_SYSTEMLanguageType(0x0000) : GetLanguage(); | |||
134 | ||||
135 | LanguageTag aLanguageTag(eLang); | |||
136 | CharClass aCharClass( aLanguageTag ); | |||
137 | ||||
138 | switch( eCaseMap ) | |||
139 | { | |||
140 | case SvxCaseMap::SmallCaps: | |||
141 | case SvxCaseMap::Uppercase: | |||
142 | { | |||
143 | aTxt = aCharClass.uppercase( aTxt ); | |||
144 | break; | |||
145 | } | |||
146 | ||||
147 | case SvxCaseMap::Lowercase: | |||
148 | { | |||
149 | aTxt = aCharClass.lowercase( aTxt ); | |||
150 | break; | |||
151 | } | |||
152 | case SvxCaseMap::Capitalize: | |||
153 | { | |||
154 | // Every beginning of a word is capitalized, the rest of the word | |||
155 | // is taken over as is. | |||
156 | // Bug: if the attribute starts in the middle of the word. | |||
157 | bool bBlank = true; | |||
158 | ||||
159 | for (sal_Int32 i = 0; i < aTxt.getLength(); ++i) | |||
160 | { | |||
161 | if( aTxt[i] == ' ' || aTxt[i] == '\t') | |||
162 | bBlank = true; | |||
163 | else | |||
164 | { | |||
165 | if (bBlank) | |||
166 | { | |||
167 | OUString sTitle(aCharClass.uppercase(OUString(aTxt[i]))); | |||
168 | aTxt = aTxt.replaceAt(i, 1, sTitle); | |||
169 | } | |||
170 | bBlank = false; | |||
171 | } | |||
172 | } | |||
173 | break; | |||
174 | } | |||
175 | default: | |||
176 | { | |||
177 | SAL_WARN( "editeng", "SvxFont::CaseMapTxt: unknown casemap")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN , "editeng")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "SvxFont::CaseMapTxt: unknown casemap" ) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("editeng" ), ("/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" ":" "177" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "SvxFont::CaseMapTxt: unknown casemap" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SvxFont::CaseMapTxt: unknown casemap"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("editeng"), ("/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" ":" "177" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "SvxFont::CaseMapTxt: unknown casemap") == 1) { :: sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("editeng"), ( "/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" ":" "177" ": "), ::sal::detail::unwrapStream( ::sal::detail:: StreamStart() << "SvxFont::CaseMapTxt: unknown casemap" ), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream << "SvxFont::CaseMapTxt: unknown casemap"; ::sal::detail ::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("editeng"), ("/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" ":" "177" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
178 | break; | |||
179 | } | |||
180 | } | |||
181 | return aTxt; | |||
182 | } | |||
183 | ||||
184 | /************************************************************************* | |||
185 | * class SvxDoCapitals | |||
186 | * The virtual Method Do si called by SvxFont::DoOnCapitals alternately | |||
187 | * the uppercase and lowercase parts. The derivate of SvxDoCapitals fills | |||
188 | * this method with life. | |||
189 | *************************************************************************/ | |||
190 | ||||
191 | class SvxDoCapitals | |||
192 | { | |||
193 | protected: | |||
194 | VclPtr<OutputDevice> pOut; | |||
195 | const OUString &rTxt; | |||
196 | const sal_Int32 nIdx; | |||
197 | const sal_Int32 nLen; | |||
198 | ||||
199 | public: | |||
200 | SvxDoCapitals( OutputDevice *_pOut, const OUString &_rTxt, | |||
201 | const sal_Int32 _nIdx, const sal_Int32 _nLen ) | |||
202 | : pOut(_pOut), rTxt(_rTxt), nIdx(_nIdx), nLen(_nLen) | |||
203 | { } | |||
204 | ||||
205 | virtual ~SvxDoCapitals() {} | |||
206 | ||||
207 | virtual void DoSpace( const bool bDraw ); | |||
208 | virtual void SetSpace(); | |||
209 | virtual void Do( const OUString &rTxt, | |||
210 | const sal_Int32 nIdx, const sal_Int32 nLen, | |||
211 | const bool bUpper ) = 0; | |||
212 | ||||
213 | const OUString &GetTxt() const { return rTxt; } | |||
214 | sal_Int32 GetIdx() const { return nIdx; } | |||
215 | sal_Int32 GetLen() const { return nLen; } | |||
216 | }; | |||
217 | ||||
218 | void SvxDoCapitals::DoSpace( const bool /*bDraw*/ ) { } | |||
219 | ||||
220 | void SvxDoCapitals::SetSpace() { } | |||
221 | ||||
222 | /************************************************************************* | |||
223 | * SvxFont::DoOnCapitals() const | |||
224 | * Decomposes the String into uppercase and lowercase letters and then | |||
225 | * calls the method SvxDoCapitals::Do( ). | |||
226 | *************************************************************************/ | |||
227 | ||||
228 | void SvxFont::DoOnCapitals(SvxDoCapitals &rDo) const | |||
229 | { | |||
230 | const OUString &rTxt = rDo.GetTxt(); | |||
231 | const sal_Int32 nIdx = rDo.GetIdx(); | |||
232 | const sal_Int32 nLen = rDo.GetLen(); | |||
233 | ||||
234 | const OUString aTxt( CalcCaseMap( rTxt ) ); | |||
235 | const sal_Int32 nTxtLen = std::min( rTxt.getLength(), nLen ); | |||
236 | sal_Int32 nPos = 0; | |||
237 | sal_Int32 nOldPos = nPos; | |||
238 | ||||
239 | // Test if string length differ between original and CaseMapped | |||
240 | bool bCaseMapLengthDiffers(aTxt.getLength() != rTxt.getLength()); | |||
241 | ||||
242 | const LanguageType eLang = LANGUAGE_DONTKNOWLanguageType(0x03FF) == GetLanguage() | |||
243 | ? LANGUAGE_SYSTEMLanguageType(0x0000) : GetLanguage(); | |||
244 | ||||
245 | LanguageTag aLanguageTag(eLang); | |||
246 | CharClass aCharClass( aLanguageTag ); | |||
247 | OUString aCharString; | |||
248 | ||||
249 | while( nPos < nTxtLen ) | |||
250 | { | |||
251 | // first in turn are the uppercase letters | |||
252 | ||||
253 | // There are characters that are both upper- and lower-case L (eg blank) | |||
254 | // Such ambiguities lead to chaos, this is why these characters are | |||
255 | // allocated to the lowercase characters! | |||
256 | ||||
257 | while( nPos < nTxtLen ) | |||
258 | { | |||
259 | aCharString = rTxt.copy( nPos + nIdx, 1 ); | |||
260 | sal_Int32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 ); | |||
261 | if ( nCharacterType & css::i18n::KCharacterType::LOWER ) | |||
262 | break; | |||
263 | if ( ! ( nCharacterType & css::i18n::KCharacterType::UPPER ) ) | |||
264 | break; | |||
265 | ++nPos; | |||
266 | } | |||
267 | if( nOldPos != nPos ) | |||
268 | { | |||
269 | if(bCaseMapLengthDiffers) | |||
270 | { | |||
271 | // If strings differ work preparing the necessary snippet to address that | |||
272 | // potential difference | |||
273 | const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos-nOldPos); | |||
274 | OUString aNewText = CalcCaseMap(aSnippet); | |||
275 | ||||
276 | rDo.Do( aNewText, 0, aNewText.getLength(), true ); | |||
277 | } | |||
278 | else | |||
279 | { | |||
280 | rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, true ); | |||
281 | } | |||
282 | ||||
283 | nOldPos = nPos; | |||
284 | } | |||
285 | // Now the lowercase are processed (without blanks) | |||
286 | while( nPos < nTxtLen ) | |||
287 | { | |||
288 | sal_uInt32 nCharacterType = aCharClass.getCharacterType( aCharString, 0 ); | |||
289 | if ( nCharacterType & css::i18n::KCharacterType::UPPER ) | |||
290 | break; | |||
291 | if ( aCharString == " " ) | |||
292 | break; | |||
293 | if( ++nPos < nTxtLen ) | |||
294 | aCharString = rTxt.copy( nPos + nIdx, 1 ); | |||
295 | } | |||
296 | if( nOldPos != nPos ) | |||
297 | { | |||
298 | if(bCaseMapLengthDiffers) | |||
299 | { | |||
300 | // If strings differ work preparing the necessary snippet to address that | |||
301 | // potential difference | |||
302 | const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos); | |||
303 | OUString aNewText = CalcCaseMap(aSnippet); | |||
304 | ||||
305 | rDo.Do( aNewText, 0, aNewText.getLength(), false ); | |||
306 | } | |||
307 | else | |||
308 | { | |||
309 | rDo.Do( aTxt, nIdx + nOldPos, nPos-nOldPos, false ); | |||
310 | } | |||
311 | ||||
312 | nOldPos = nPos; | |||
313 | } | |||
314 | // Now the blanks are<processed | |||
315 | while( nPos < nTxtLen && aCharString == " " && ++nPos < nTxtLen ) | |||
316 | aCharString = rTxt.copy( nPos + nIdx, 1 ); | |||
317 | ||||
318 | if( nOldPos != nPos ) | |||
319 | { | |||
320 | rDo.DoSpace( false ); | |||
321 | ||||
322 | if(bCaseMapLengthDiffers) | |||
323 | { | |||
324 | // If strings differ work preparing the necessary snippet to address that | |||
325 | // potential difference | |||
326 | const OUString aSnippet = rTxt.copy(nIdx + nOldPos, nPos - nOldPos); | |||
327 | OUString aNewText = CalcCaseMap(aSnippet); | |||
328 | ||||
329 | rDo.Do( aNewText, 0, aNewText.getLength(), false ); | |||
330 | } | |||
331 | else | |||
332 | { | |||
333 | rDo.Do( aTxt, nIdx + nOldPos, nPos - nOldPos, false ); | |||
334 | } | |||
335 | ||||
336 | nOldPos = nPos; | |||
337 | rDo.SetSpace(); | |||
338 | } | |||
339 | } | |||
340 | rDo.DoSpace( true ); | |||
341 | } | |||
342 | ||||
343 | ||||
344 | void SvxFont::SetPhysFont( OutputDevice *pOut ) const | |||
345 | { | |||
346 | const vcl::Font& rCurrentFont = pOut->GetFont(); | |||
347 | if ( nPropr == 100 ) | |||
348 | { | |||
349 | if ( !rCurrentFont.IsSameInstance( *this ) ) | |||
350 | pOut->SetFont( *this ); | |||
351 | } | |||
352 | else | |||
353 | { | |||
354 | Font aNewFont( *this ); | |||
355 | Size aSize( aNewFont.GetFontSize() ); | |||
356 | aNewFont.SetFontSize( Size( aSize.Width() * nPropr / 100, | |||
357 | aSize.Height() * nPropr / 100 ) ); | |||
358 | if ( !rCurrentFont.IsSameInstance( aNewFont ) ) | |||
359 | pOut->SetFont( aNewFont ); | |||
360 | } | |||
361 | } | |||
362 | ||||
363 | ||||
364 | vcl::Font SvxFont::ChgPhysFont( OutputDevice *pOut ) const | |||
365 | { | |||
366 | vcl::Font aOldFont( pOut->GetFont() ); | |||
367 | SetPhysFont( pOut ); | |||
368 | return aOldFont; | |||
369 | } | |||
370 | ||||
371 | ||||
372 | Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut, const OUString &rTxt, | |||
373 | const sal_Int32 nIdx, const sal_Int32 nLen ) const | |||
374 | { | |||
375 | if ( !IsCaseMap() && !IsKern() ) | |||
376 | return Size( pOut->GetTextWidth( rTxt, nIdx, nLen ), | |||
377 | pOut->GetTextHeight() ); | |||
378 | ||||
379 | Size aTxtSize; | |||
380 | aTxtSize.setHeight( pOut->GetTextHeight() ); | |||
381 | if ( !IsCaseMap() ) | |||
382 | aTxtSize.setWidth( pOut->GetTextWidth( rTxt, nIdx, nLen ) ); | |||
383 | else | |||
384 | { | |||
385 | const OUString aNewText = CalcCaseMap(rTxt); | |||
386 | bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength()); | |||
387 | sal_Int32 nWidth(0); | |||
388 | ||||
389 | if(bCaseMapLengthDiffers) | |||
390 | { | |||
391 | // If strings differ work preparing the necessary snippet to address that | |||
392 | // potential difference | |||
393 | const OUString aSnippet = rTxt.copy(nIdx, nLen); | |||
394 | OUString _aNewText = CalcCaseMap(aSnippet); | |||
395 | nWidth = pOut->GetTextWidth( _aNewText, 0, _aNewText.getLength() ); | |||
396 | } | |||
397 | else | |||
398 | { | |||
399 | nWidth = pOut->GetTextWidth( aNewText, nIdx, nLen ); | |||
400 | } | |||
401 | ||||
402 | aTxtSize.setWidth(nWidth); | |||
403 | } | |||
404 | ||||
405 | if( IsKern() && ( nLen > 1 ) ) | |||
406 | aTxtSize.AdjustWidth( ( nLen-1 ) * long( nKern ) ); | |||
407 | ||||
408 | return aTxtSize; | |||
409 | } | |||
410 | ||||
411 | Size SvxFont::GetPhysTxtSize( const OutputDevice *pOut ) | |||
412 | { | |||
413 | if ( !IsCaseMap() && !IsKern() ) | |||
414 | return Size( pOut->GetTextWidth( "" ), pOut->GetTextHeight() ); | |||
415 | ||||
416 | Size aTxtSize; | |||
417 | aTxtSize.setHeight( pOut->GetTextHeight() ); | |||
418 | if ( !IsCaseMap() ) | |||
419 | aTxtSize.setWidth( pOut->GetTextWidth( "" ) ); | |||
420 | else | |||
421 | aTxtSize.setWidth( pOut->GetTextWidth( CalcCaseMap( "" ) ) ); | |||
422 | ||||
423 | return aTxtSize; | |||
424 | } | |||
425 | ||||
426 | Size SvxFont::QuickGetTextSize( const OutputDevice *pOut, const OUString &rTxt, | |||
427 | const sal_Int32 nIdx, const sal_Int32 nLen, long* pDXArray ) const | |||
428 | { | |||
429 | if ( !IsCaseMap() && !IsKern() ) | |||
430 | return Size( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ), | |||
431 | pOut->GetTextHeight() ); | |||
432 | ||||
433 | Size aTxtSize; | |||
434 | aTxtSize.setHeight( pOut->GetTextHeight() ); | |||
435 | if ( !IsCaseMap() ) | |||
436 | aTxtSize.setWidth( pOut->GetTextArray( rTxt, pDXArray, nIdx, nLen ) ); | |||
437 | else | |||
438 | aTxtSize.setWidth( pOut->GetTextArray( CalcCaseMap( rTxt ), | |||
439 | pDXArray, nIdx, nLen ) ); | |||
440 | ||||
441 | if( IsKern() && ( nLen > 1 ) ) | |||
442 | { | |||
443 | aTxtSize.AdjustWidth( ( nLen-1 ) * long( nKern ) ); | |||
444 | ||||
445 | if ( pDXArray ) | |||
446 | { | |||
447 | for ( sal_Int32 i = 0; i < nLen; i++ ) | |||
448 | pDXArray[i] += ( (i+1) * long( nKern ) ); | |||
449 | // The last one is a nKern too big: | |||
450 | pDXArray[nLen-1] -= nKern; | |||
451 | } | |||
452 | } | |||
453 | return aTxtSize; | |||
454 | } | |||
455 | ||||
456 | ||||
457 | Size SvxFont::GetTextSize( const OutputDevice *pOut, const OUString &rTxt, | |||
458 | const sal_Int32 nIdx, const sal_Int32 nLen ) const | |||
459 | { | |||
460 | sal_Int32 nTmp = nLen; | |||
461 | if ( nTmp == SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) ) // already initialized? | |||
462 | nTmp = rTxt.getLength(); | |||
463 | Font aOldFont( ChgPhysFont(const_cast<OutputDevice *>(pOut)) ); | |||
464 | Size aTxtSize; | |||
465 | if( IsCapital() && !rTxt.isEmpty() ) | |||
466 | { | |||
467 | aTxtSize = GetCapitalSize( pOut, rTxt, nIdx, nTmp ); | |||
468 | } | |||
469 | else aTxtSize = GetPhysTxtSize(pOut,rTxt,nIdx,nTmp); | |||
470 | const_cast<OutputDevice *>(pOut)->SetFont( aOldFont ); | |||
471 | return aTxtSize; | |||
472 | } | |||
473 | ||||
474 | ||||
475 | void SvxFont::QuickDrawText( OutputDevice *pOut, | |||
476 | const Point &rPos, const OUString &rTxt, | |||
477 | const sal_Int32 nIdx, const sal_Int32 nLen, const long* pDXArray ) const | |||
478 | { | |||
479 | ||||
480 | // Font has to be selected in OutputDevice... | |||
481 | if ( !IsCaseMap() && !IsCapital() && !IsKern() && !IsEsc() ) | |||
482 | { | |||
483 | pOut->DrawTextArray( rPos, rTxt, pDXArray, nIdx, nLen ); | |||
484 | return; | |||
485 | } | |||
486 | ||||
487 | Point aPos( rPos ); | |||
488 | ||||
489 | if ( nEsc ) | |||
490 | { | |||
491 | long nDiff = GetFontSize().Height(); | |||
492 | nDiff *= nEsc; | |||
493 | nDiff /= 100; | |||
494 | ||||
495 | if ( !IsVertical() ) | |||
496 | aPos.AdjustY( -nDiff ); | |||
497 | else | |||
498 | aPos.AdjustX(nDiff ); | |||
499 | } | |||
500 | ||||
501 | if( IsCapital() ) | |||
502 | { | |||
503 | DBG_ASSERT( !pDXArray, "DrawCapital not for TextArray!" )do { if (true && (!(!pDXArray))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" ":" "503" ": "), "%s", "DrawCapital not for TextArray!"); } } while (false); | |||
504 | DrawCapital( pOut, aPos, rTxt, nIdx, nLen ); | |||
505 | } | |||
506 | else | |||
507 | { | |||
508 | if ( IsKern() && !pDXArray ) | |||
509 | { | |||
510 | Size aSize = GetPhysTxtSize( pOut, rTxt, nIdx, nLen ); | |||
511 | ||||
512 | if ( !IsCaseMap() ) | |||
513 | pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nLen ); | |||
514 | else | |||
515 | pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nLen ); | |||
516 | } | |||
517 | else | |||
518 | { | |||
519 | if ( !IsCaseMap() ) | |||
520 | pOut->DrawTextArray( aPos, rTxt, pDXArray, nIdx, nLen ); | |||
521 | else | |||
522 | pOut->DrawTextArray( aPos, CalcCaseMap( rTxt ), pDXArray, nIdx, nLen ); | |||
523 | } | |||
524 | } | |||
525 | } | |||
526 | ||||
527 | ||||
528 | void SvxFont::DrawPrev( OutputDevice *pOut, Printer* pPrinter, | |||
529 | const Point &rPos, const OUString &rTxt, | |||
530 | const sal_Int32 nIdx, const sal_Int32 nLen ) const | |||
531 | { | |||
532 | if ( !nLen || rTxt.isEmpty() ) | |||
| ||||
533 | return; | |||
534 | sal_Int32 nTmp = nLen; | |||
535 | ||||
536 | if ( nTmp == SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) ) // already initialized? | |||
537 | nTmp = rTxt.getLength(); | |||
538 | Point aPos( rPos ); | |||
539 | ||||
540 | if ( nEsc ) | |||
541 | { | |||
542 | short nTmpEsc; | |||
543 | if( DFLT_ESC_AUTO_SUPER(13999 +1) == nEsc ) | |||
544 | { | |||
545 | nTmpEsc = .8 * (100 - nPropr); | |||
546 | assert (nTmpEsc == DFLT_ESC_SUPER && "I'm sure this formula needs to be changed, but how to confirm that???")(static_cast <bool> (nTmpEsc == 33 && "I'm sure this formula needs to be changed, but how to confirm that???" ) ? void (0) : __assert_fail ("nTmpEsc == DFLT_ESC_SUPER && \"I'm sure this formula needs to be changed, but how to confirm that???\"" , "/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" , 546, __extension__ __PRETTY_FUNCTION__)); | |||
547 | nTmpEsc = DFLT_ESC_SUPER33; | |||
548 | } | |||
549 | else if( DFLT_ESC_AUTO_SUB-(13999 +1) == nEsc ) | |||
550 | { | |||
551 | nTmpEsc = .2 * -(100 - nPropr); | |||
552 | assert (nTmpEsc == -20 && "I'm sure this formula needs to be changed, but how to confirm that???")(static_cast <bool> (nTmpEsc == -20 && "I'm sure this formula needs to be changed, but how to confirm that???" ) ? void (0) : __assert_fail ("nTmpEsc == -20 && \"I'm sure this formula needs to be changed, but how to confirm that???\"" , "/home/maarten/src/libreoffice/core/editeng/source/items/svxfont.cxx" , 552, __extension__ __PRETTY_FUNCTION__)); | |||
553 | nTmpEsc = -20; | |||
554 | } | |||
555 | else | |||
556 | nTmpEsc = nEsc; | |||
557 | Size aSize = GetFontSize(); | |||
558 | aPos.AdjustY( -(( nTmpEsc * aSize.Height() ) / 100) ); | |||
559 | } | |||
560 | Font aOldFont( ChgPhysFont( pOut ) ); | |||
561 | Font aOldPrnFont( ChgPhysFont( pPrinter ) ); | |||
562 | ||||
563 | if ( IsCapital() ) | |||
564 | DrawCapital( pOut, aPos, rTxt, nIdx, nTmp ); | |||
565 | else | |||
566 | { | |||
567 | Size aSize = GetPhysTxtSize( pPrinter, rTxt, nIdx, nTmp ); | |||
568 | ||||
569 | if ( !IsCaseMap() ) | |||
570 | pOut->DrawStretchText( aPos, aSize.Width(), rTxt, nIdx, nTmp ); | |||
571 | else | |||
572 | { | |||
573 | const OUString aNewText = CalcCaseMap(rTxt); | |||
574 | bool bCaseMapLengthDiffers(aNewText.getLength() != rTxt.getLength()); | |||
575 | ||||
576 | if(bCaseMapLengthDiffers) | |||
577 | { | |||
578 | // If strings differ work preparing the necessary snippet to address that | |||
579 | // potential difference | |||
580 | const OUString aSnippet(rTxt.copy( nIdx, nTmp)); | |||
581 | OUString _aNewText = CalcCaseMap(aSnippet); | |||
582 | ||||
583 | pOut->DrawStretchText( aPos, aSize.Width(), _aNewText, 0, _aNewText.getLength() ); | |||
584 | } | |||
585 | else | |||
586 | { | |||
587 | pOut->DrawStretchText( aPos, aSize.Width(), CalcCaseMap( rTxt ), nIdx, nTmp ); | |||
588 | } | |||
589 | } | |||
590 | } | |||
591 | pOut->SetFont(aOldFont); | |||
| ||||
592 | pPrinter->SetFont( aOldPrnFont ); | |||
593 | } | |||
594 | ||||
595 | ||||
596 | SvxFont& SvxFont::operator=( const vcl::Font& rFont ) | |||
597 | { | |||
598 | Font::operator=( rFont ); | |||
599 | return *this; | |||
600 | } | |||
601 | ||||
602 | SvxFont& SvxFont::operator=( const SvxFont& rFont ) | |||
603 | { | |||
604 | Font::operator=( rFont ); | |||
605 | eCaseMap = rFont.eCaseMap; | |||
606 | nEsc = rFont.nEsc; | |||
607 | nPropr = rFont.nPropr; | |||
608 | nKern = rFont.nKern; | |||
609 | return *this; | |||
610 | } | |||
611 | ||||
612 | namespace { | |||
613 | ||||
614 | class SvxDoGetCapitalSize : public SvxDoCapitals | |||
615 | { | |||
616 | protected: | |||
617 | SvxFont* pFont; | |||
618 | Size aTxtSize; | |||
619 | short nKern; | |||
620 | public: | |||
621 | SvxDoGetCapitalSize( SvxFont *_pFnt, const OutputDevice *_pOut, | |||
622 | const OUString &_rTxt, const sal_Int32 _nIdx, | |||
623 | const sal_Int32 _nLen, const short _nKrn ) | |||
624 | : SvxDoCapitals( const_cast<OutputDevice*>(_pOut), _rTxt, _nIdx, _nLen ), | |||
625 | pFont( _pFnt ), | |||
626 | nKern( _nKrn ) | |||
627 | { } | |||
628 | ||||
629 | virtual void Do( const OUString &rTxt, const sal_Int32 nIdx, | |||
630 | const sal_Int32 nLen, const bool bUpper ) override; | |||
631 | ||||
632 | const Size &GetSize() const { return aTxtSize; }; | |||
633 | }; | |||
634 | ||||
635 | } | |||
636 | ||||
637 | void SvxDoGetCapitalSize::Do( const OUString &_rTxt, const sal_Int32 _nIdx, | |||
638 | const sal_Int32 _nLen, const bool bUpper ) | |||
639 | { | |||
640 | Size aPartSize; | |||
641 | if ( !bUpper ) | |||
642 | { | |||
643 | sal_uInt8 nProp = pFont->GetPropr(); | |||
644 | pFont->SetProprRel( SMALL_CAPS_PERCENTAGE80 ); | |||
645 | pFont->SetPhysFont( pOut ); | |||
646 | aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); | |||
647 | aPartSize.setHeight( pOut->GetTextHeight() ); | |||
648 | aTxtSize.setHeight( aPartSize.Height() ); | |||
649 | pFont->SetPropr( nProp ); | |||
650 | pFont->SetPhysFont( pOut ); | |||
651 | } | |||
652 | else | |||
653 | { | |||
654 | aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); | |||
655 | aPartSize.setHeight( pOut->GetTextHeight() ); | |||
656 | } | |||
657 | aTxtSize.AdjustWidth(aPartSize.Width() ); | |||
658 | aTxtSize.AdjustWidth( _nLen * long( nKern ) ); | |||
659 | } | |||
660 | ||||
661 | Size SvxFont::GetCapitalSize( const OutputDevice *pOut, const OUString &rTxt, | |||
662 | const sal_Int32 nIdx, const sal_Int32 nLen) const | |||
663 | { | |||
664 | // Start: | |||
665 | SvxDoGetCapitalSize aDo( const_cast<SvxFont *>(this), pOut, rTxt, nIdx, nLen, nKern ); | |||
666 | DoOnCapitals( aDo ); | |||
667 | Size aTxtSize( aDo.GetSize() ); | |||
668 | ||||
669 | // End: | |||
670 | if( !aTxtSize.Height() ) | |||
671 | { | |||
672 | aTxtSize.setWidth( 0 ); | |||
673 | aTxtSize.setHeight( pOut->GetTextHeight() ); | |||
674 | } | |||
675 | return aTxtSize; | |||
676 | } | |||
677 | ||||
678 | namespace { | |||
679 | ||||
680 | class SvxDoDrawCapital : public SvxDoCapitals | |||
681 | { | |||
682 | protected: | |||
683 | SvxFont *pFont; | |||
684 | Point aPos; | |||
685 | Point aSpacePos; | |||
686 | short nKern; | |||
687 | public: | |||
688 | SvxDoDrawCapital( SvxFont *pFnt, OutputDevice *_pOut, const OUString &_rTxt, | |||
689 | const sal_Int32 _nIdx, const sal_Int32 _nLen, | |||
690 | const Point &rPos, const short nKrn ) | |||
691 | : SvxDoCapitals( _pOut, _rTxt, _nIdx, _nLen ), | |||
692 | pFont( pFnt ), | |||
693 | aPos( rPos ), | |||
694 | aSpacePos( rPos ), | |||
695 | nKern( nKrn ) | |||
696 | { } | |||
697 | virtual void DoSpace( const bool bDraw ) override; | |||
698 | virtual void SetSpace() override; | |||
699 | virtual void Do( const OUString &rTxt, const sal_Int32 nIdx, | |||
700 | const sal_Int32 nLen, const bool bUpper ) override; | |||
701 | }; | |||
702 | ||||
703 | } | |||
704 | ||||
705 | void SvxDoDrawCapital::DoSpace( const bool bDraw ) | |||
706 | { | |||
707 | if ( !(bDraw || pFont->IsWordLineMode()) ) | |||
708 | return; | |||
709 | ||||
710 | sal_uLong nDiff = static_cast<sal_uLong>(aPos.X() - aSpacePos.X()); | |||
711 | if ( nDiff ) | |||
712 | { | |||
713 | bool bWordWise = pFont->IsWordLineMode(); | |||
714 | bool bTrans = pFont->IsTransparent(); | |||
715 | pFont->SetWordLineMode( false ); | |||
716 | pFont->SetTransparent( true ); | |||
717 | pFont->SetPhysFont( pOut ); | |||
718 | pOut->DrawStretchText( aSpacePos, nDiff, " ", 0, 2 ); | |||
719 | pFont->SetWordLineMode( bWordWise ); | |||
720 | pFont->SetTransparent( bTrans ); | |||
721 | pFont->SetPhysFont( pOut ); | |||
722 | } | |||
723 | } | |||
724 | ||||
725 | void SvxDoDrawCapital::SetSpace() | |||
726 | { | |||
727 | if ( pFont->IsWordLineMode() ) | |||
728 | aSpacePos.setX( aPos.X() ); | |||
729 | } | |||
730 | ||||
731 | void SvxDoDrawCapital::Do( const OUString &_rTxt, const sal_Int32 _nIdx, | |||
732 | const sal_Int32 _nLen, const bool bUpper) | |||
733 | { | |||
734 | sal_uInt8 nProp = 0; | |||
735 | Size aPartSize; | |||
736 | ||||
737 | // Set the desired font | |||
738 | FontLineStyle eUnder = pFont->GetUnderline(); | |||
739 | FontStrikeout eStrike = pFont->GetStrikeout(); | |||
740 | pFont->SetUnderline( LINESTYLE_NONE ); | |||
741 | pFont->SetStrikeout( STRIKEOUT_NONE ); | |||
742 | if ( !bUpper ) | |||
743 | { | |||
744 | nProp = pFont->GetPropr(); | |||
745 | pFont->SetProprRel( SMALL_CAPS_PERCENTAGE80 ); | |||
746 | } | |||
747 | pFont->SetPhysFont( pOut ); | |||
748 | ||||
749 | aPartSize.setWidth( pOut->GetTextWidth( _rTxt, _nIdx, _nLen ) ); | |||
750 | aPartSize.setHeight( pOut->GetTextHeight() ); | |||
751 | long nWidth = aPartSize.Width(); | |||
752 | if ( nKern ) | |||
753 | { | |||
754 | aPos.AdjustX(nKern/2); | |||
755 | if ( _nLen ) nWidth += (_nLen*long(nKern)); | |||
756 | } | |||
757 | pOut->DrawStretchText(aPos,nWidth-nKern,_rTxt,_nIdx,_nLen); | |||
758 | ||||
759 | // Restore Font | |||
760 | pFont->SetUnderline( eUnder ); | |||
761 | pFont->SetStrikeout( eStrike ); | |||
762 | if ( !bUpper ) | |||
763 | pFont->SetPropr( nProp ); | |||
764 | pFont->SetPhysFont( pOut ); | |||
765 | ||||
766 | aPos.AdjustX(nWidth-(nKern/2) ); | |||
767 | } | |||
768 | ||||
769 | /************************************************************************* | |||
770 | * SvxFont::DrawCapital() draws the uppercase letter. | |||
771 | *************************************************************************/ | |||
772 | ||||
773 | void SvxFont::DrawCapital( OutputDevice *pOut, | |||
774 | const Point &rPos, const OUString &rTxt, | |||
775 | const sal_Int32 nIdx, const sal_Int32 nLen ) const | |||
776 | { | |||
777 | SvxDoDrawCapital aDo( const_cast<SvxFont *>(this),pOut,rTxt,nIdx,nLen,rPos,nKern ); | |||
778 | DoOnCapitals( aDo ); | |||
779 | } | |||
780 | ||||
781 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | |||||||
34 | namespace rtl | ||||||
35 | { | ||||||
36 | |||||||
37 | /** Template reference class for reference type. | ||||||
38 | */ | ||||||
39 | template <class reference_type> | ||||||
40 | class Reference | ||||||
41 | { | ||||||
42 | /** The <b>reference_type</b> body pointer. | ||||||
43 | */ | ||||||
44 | reference_type * m_pBody; | ||||||
45 | |||||||
46 | |||||||
47 | public: | ||||||
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) | ||||||
177 | { | ||||||
178 | reference_type * const pOld = m_pBody; | ||||||
179 | m_pBody = NULL__null; | ||||||
180 | pOld->release(); | ||||||
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; | ||||||
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 | ||||||
277 | namespace 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 | */ | ||||||
286 | template<typename T> | ||||||
287 | struct 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: */ |
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 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
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) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |