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 ogl_canvashelper.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/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/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/canvas/inc -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/canvas/source/opengl/ogl_canvashelper.cxx

/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.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
10#include <sal/config.h>
11
12#include <memory>
13#include <functional>
14#include <epoxy/gl.h>
15
16#include <basegfx/matrix/b2dhommatrix.hxx>
17#include <basegfx/polygon/b2dpolypolygon.hxx>
18#include <basegfx/polygon/b2dpolypolygontools.hxx>
19#include <basegfx/utils/canvastools.hxx>
20#include <com/sun/star/rendering/CompositeOperation.hpp>
21#include <rtl/crc.h>
22#include <rtl/math.hxx>
23#include <tools/diagnose_ex.h>
24#include <vcl/font.hxx>
25#include <vcl/metric.hxx>
26#include <vcl/virdev.hxx>
27
28#include "ogl_canvasbitmap.hxx"
29#include "ogl_canvasfont.hxx"
30#include "ogl_canvastools.hxx"
31#include "ogl_texturecache.hxx"
32#include "ogl_tools.hxx"
33
34#include "ogl_canvashelper.hxx"
35
36using namespace ::com::sun::star;
37using namespace std::placeholders;
38
39namespace oglcanvas
40{
41 /* Concepts:
42 =========
43
44 This OpenGL canvas implementation tries to keep all render
45 output as high-level as possible, i.e. geometry data and
46 externally-provided bitmaps. Therefore, calls at the
47 XCanvas-interfaces are not immediately transformed into colored
48 pixel inside some GL buffer, but are retained simply with their
49 call parameters. Only after XSpriteCanvas::updateScreen() has
50 been called, this all gets transferred to the OpenGL subsystem
51 and converted to a visible scene. The big advantage is, this
52 makes sprite modifications practically zero-overhead, and saves
53 a lot on texture memory (compared to the directx canvas, which
54 immediately dumps every render call into a texture).
55
56 The drawback, of course, is that complex images churn a lot of
57 GPU cycles on every re-rendering.
58
59 For the while, I'll be using immediate mode, i.e. transfer data
60 over and over again to the OpenGL subsystem. Alternatively,
61 there are display lists, which at least keep the data on the
62 server, or even better, vertex buffers, which copy geometry
63 data over en bloc.
64
65 Next todo: put polygon geometry into vertex buffer (LRU cache
66 necessary?) - or, rather, buffer objects! prune entries older
67 than one updateScreen() call)
68
69 Text: http://www.opengl.org/resources/features/fontsurvey/
70 */
71
72 struct CanvasHelper::Action
73 {
74 ::basegfx::B2DHomMatrix maTransform;
75 GLenum meSrcBlendMode;
76 GLenum meDstBlendMode;
77 rendering::ARGBColor maARGBColor;
78 ::basegfx::B2DPolyPolygonVector maPolyPolys;
79
80 std::function< bool (
81 const CanvasHelper&,
82 const ::basegfx::B2DHomMatrix&,
83 GLenum,
84 GLenum,
85 const rendering::ARGBColor&,
86 const ::basegfx::B2DPolyPolygonVector&)> maFunction;
87 };
88
89 namespace
90 {
91 bool lcl_drawLine( const CanvasHelper& /*rHelper*/,
92 const ::basegfx::B2DHomMatrix& rTransform,
93 GLenum eSrcBlend,
94 GLenum eDstBlend,
95 const rendering::ARGBColor& rColor,
96 const geometry::RealPoint2D& rStartPoint,
97 const geometry::RealPoint2D& rEndPoint )
98 {
99 TransformationPreserver aPreserver;
100 setupState(rTransform, eSrcBlend, eDstBlend, rColor);
101
102 glBeginepoxy_glBegin(GL_LINES0x0001);
103 glVertex2depoxy_glVertex2d(rStartPoint.X, rStartPoint.Y);
104 glVertex2depoxy_glVertex2d(rEndPoint.X, rEndPoint.Y);
105 glEndepoxy_glEnd();
106
107 return true;
108 }
109
110 bool lcl_drawPolyPolygon( const CanvasHelper& /*rHelper*/,
111 const ::basegfx::B2DHomMatrix& rTransform,
112 GLenum eSrcBlend,
113 GLenum eDstBlend,
114 const rendering::ARGBColor& rColor,
115 const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
116 {
117 TransformationPreserver aPreserver;
118 setupState(rTransform, eSrcBlend, eDstBlend, rColor);
119
120 for( const auto& rPoly : rPolyPolygons )
121 renderPolyPolygon( rPoly );
122
123 return true;
124 }
125
126 bool lcl_fillPolyPolygon( const CanvasHelper& /*rHelper*/,
127 const ::basegfx::B2DHomMatrix& rTransform,
128 GLenum eSrcBlend,
129 GLenum eDstBlend,
130 const rendering::ARGBColor& rColor,
131 const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
132 {
133 TransformationPreserver aPreserver;
134 setupState(rTransform, eSrcBlend, eDstBlend, rColor);
135
136 for( const auto& rPoly : rPolyPolygons )
137 {
138 glBeginepoxy_glBegin( GL_TRIANGLES0x0004 );
139 renderComplexPolyPolygon( rPoly );
140 glEndepoxy_glEnd();
141 }
142
143 return true;
144 }
145
146 bool lcl_fillGradientPolyPolygon( const CanvasHelper& rHelper,
147 const ::basegfx::B2DHomMatrix& rTransform,
148 GLenum eSrcBlend,
149 GLenum eDstBlend,
150 const ::canvas::ParametricPolyPolygon::Values& rValues,
151 const rendering::Texture& rTexture,
152 const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
153 {
154 TransformationPreserver aPreserver;
155 setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
156
157 // convert to weird canvas textur coordinate system (not
158 // [0,1]^2, but path coordinate system)
159 ::basegfx::B2DHomMatrix aTextureTransform;
160 ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
161 rTexture.AffineTransform );
162 ::basegfx::B2DRange aBounds;
163 for( const auto& rPoly : rPolyPolygons )
164 aBounds.expand( ::basegfx::utils::getRange( rPoly ) );
165 aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
166 aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
167
168 const sal_Int32 nNumCols=rValues.maColors.getLength();
169 uno::Sequence< rendering::ARGBColor > aColors(nNumCols);
170 rendering::ARGBColor* const pColors=aColors.getArray();
171 rendering::ARGBColor* pCurrCol=pColors;
172 for( sal_Int32 i=0; i<nNumCols; ++i )
173 *pCurrCol++ = rHelper.getDevice()->getDeviceColorSpace()->convertToARGB(rValues.maColors[i])[0];
174
175 OSL_ASSERT(nNumCols == rValues.maStops.getLength())do { if (true && (!(nNumCols == rValues.maStops.getLength
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "175" ": "), "OSL_ASSERT: %s", "nNumCols == rValues.maStops.getLength()"
); } } while (false)
;
176
177 switch( rValues.meType )
178 {
179 case ::canvas::ParametricPolyPolygon::GradientType::Linear:
180 rHelper.getDeviceHelper()->useLinearGradientShader(pColors,
181 rValues.maStops,
182 aTextureTransform);
183 break;
184
185 case ::canvas::ParametricPolyPolygon::GradientType::Elliptical:
186 rHelper.getDeviceHelper()->useRadialGradientShader(pColors,
187 rValues.maStops,
188 aTextureTransform);
189 break;
190
191 case ::canvas::ParametricPolyPolygon::GradientType::Rectangular:
192 rHelper.getDeviceHelper()->useRectangularGradientShader(pColors,
193 rValues.maStops,
194 aTextureTransform);
195 break;
196
197 default:
198 ENSURE_OR_THROW( false,if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "199" ": "), "%s", "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case"
), css::uno::Reference< css::uno::XInterface >() ); }
199 "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case" )if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "199" ": "), "%s", "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper lcl_fillGradientPolyPolygon(): Unexpected case"
), css::uno::Reference< css::uno::XInterface >() ); }
;
200 }
201
202
203 for( const auto& rPoly : rPolyPolygons )
204 {
205 glBeginepoxy_glBegin(GL_TRIANGLES0x0004);
206 renderComplexPolyPolygon( rPoly );
207 glEndepoxy_glEnd();
208 }
209
210 glUseProgramepoxy_glUseProgram(0);
211 glLoadIdentityepoxy_glLoadIdentity();
212 glMatrixModeepoxy_glMatrixMode(GL_MODELVIEW0x1700);
213
214 return true;
215 }
216
217 bool lcl_drawOwnBitmap( const CanvasHelper& /*rHelper*/,
218 const ::basegfx::B2DHomMatrix& rTransform,
219 GLenum eSrcBlend,
220 GLenum eDstBlend,
221 const rendering::ARGBColor& rColor,
222 const CanvasBitmap& rBitmap )
223 {
224 TransformationPreserver aPreserver;
225 setupState(rTransform, eSrcBlend, eDstBlend, rColor);
226
227 return rBitmap.renderRecordedActions();
228 }
229
230 bool lcl_drawGenericBitmap( const CanvasHelper& rHelper,
231 const ::basegfx::B2DHomMatrix& rTransform,
232 GLenum eSrcBlend,
233 GLenum eDstBlend,
234 const rendering::ARGBColor& rColor,
235 const geometry::IntegerSize2D& rPixelSize,
236 const uno::Sequence<sal_Int8>& rPixelData,
237 sal_uInt32 nPixelCrc32 )
238 {
239 TransformationPreserver aPreserver;
240 setupState(rTransform, eSrcBlend, eDstBlend, rColor);
241
242 const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
243 rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
244
245 glBindTextureepoxy_glBindTexture(GL_TEXTURE_2D0x0DE1, nTexId);
246 glEnableepoxy_glEnable(GL_TEXTURE_2D0x0DE1);
247 glTexParameteriepoxy_glTexParameteri(GL_TEXTURE_2D0x0DE1,
248 GL_TEXTURE_MIN_FILTER0x2801,
249 GL_NEAREST0x2600);
250 glTexParameteriepoxy_glTexParameteri(GL_TEXTURE_2D0x0DE1,
251 GL_TEXTURE_MAG_FILTER0x2800,
252 GL_NEAREST0x2600);
253 glEnableepoxy_glEnable(GL_BLEND0x0BE2);
254 glBlendFuncepoxy_glBlendFunc(GL_SRC_ALPHA0x0302,
255 GL_ONE_MINUS_SRC_ALPHA0x0303);
256
257 // blend against fixed vertex color; texture alpha is multiplied in
258 glColor4fepoxy_glColor4f(1,1,1,1);
259
260 glBeginepoxy_glBegin(GL_TRIANGLE_STRIP0x0005);
261 glTexCoord2fepoxy_glTexCoord2f(0,0); glVertex2depoxy_glVertex2d(0,0);
262 glTexCoord2fepoxy_glTexCoord2f(0,1); glVertex2depoxy_glVertex2d(0, rPixelSize.Height);
263 glTexCoord2fepoxy_glTexCoord2f(1,0); glVertex2depoxy_glVertex2d(rPixelSize.Width,0);
264 glTexCoord2fepoxy_glTexCoord2f(1,1); glVertex2depoxy_glVertex2d(rPixelSize.Width,rPixelSize.Height);
265 glEndepoxy_glEnd();
266
267 glBindTextureepoxy_glBindTexture(GL_TEXTURE_2D0x0DE1, 0);
268 glDisableepoxy_glDisable(GL_TEXTURE_2D0x0DE1);
269
270 return true;
271 }
272
273 bool lcl_fillTexturedPolyPolygon( const CanvasHelper& rHelper,
274 const ::basegfx::B2DHomMatrix& rTransform,
275 GLenum eSrcBlend,
276 GLenum eDstBlend,
277 const rendering::Texture& rTexture,
278 const geometry::IntegerSize2D& rPixelSize,
279 const uno::Sequence<sal_Int8>& rPixelData,
280 sal_uInt32 nPixelCrc32,
281 const ::basegfx::B2DPolyPolygonVector& rPolyPolygons )
282 {
283 TransformationPreserver aPreserver;
284 setupState(rTransform, eSrcBlend, eDstBlend, rendering::ARGBColor());
285
286 const unsigned int nTexId=rHelper.getDeviceHelper()->getTextureCache().getTexture(
287 rPixelSize, rPixelData.getConstArray(), nPixelCrc32);
288
289 glBindTextureepoxy_glBindTexture(GL_TEXTURE_2D0x0DE1, nTexId);
290 glEnableepoxy_glEnable(GL_TEXTURE_2D0x0DE1);
291 glTexParameteriepoxy_glTexParameteri(GL_TEXTURE_2D0x0DE1,
292 GL_TEXTURE_MIN_FILTER0x2801,
293 GL_NEAREST0x2600);
294 glTexParameteriepoxy_glTexParameteri(GL_TEXTURE_2D0x0DE1,
295 GL_TEXTURE_MAG_FILTER0x2800,
296 GL_NEAREST0x2600);
297 glEnableepoxy_glEnable(GL_BLEND0x0BE2);
298 glBlendFuncepoxy_glBlendFunc(GL_SRC_ALPHA0x0302,
299 GL_ONE_MINUS_SRC_ALPHA0x0303);
300
301 // convert to weird canvas textur coordinate system (not
302 // [0,1]^2, but path coordinate system)
303 ::basegfx::B2DHomMatrix aTextureTransform;
304 ::basegfx::unotools::homMatrixFromAffineMatrix( aTextureTransform,
305 rTexture.AffineTransform );
306 ::basegfx::B2DRange aBounds;
307 for( const auto& rPolyPolygon : rPolyPolygons )
308 aBounds.expand( ::basegfx::utils::getRange( rPolyPolygon ) );
309 aTextureTransform.translate(-aBounds.getMinX(), -aBounds.getMinY());
310 aTextureTransform.scale(1/aBounds.getWidth(), 1/aBounds.getHeight());
311 aTextureTransform.invert();
312
313 glMatrixModeepoxy_glMatrixMode(GL_TEXTURE0x1702);
314 double aTexTransform[] =
315 {
316 aTextureTransform.get(0,0), aTextureTransform.get(1,0), 0, 0,
317 aTextureTransform.get(0,1), aTextureTransform.get(1,1), 0, 0,
318 0, 0, 1, 0,
319 aTextureTransform.get(0,2), aTextureTransform.get(1,2), 0, 1
320 };
321 glLoadMatrixdepoxy_glLoadMatrixd(aTexTransform);
322
323 // blend against fixed vertex color; texture alpha is multiplied in
324 glColor4fepoxy_glColor4f(1,1,1,rTexture.Alpha);
325
326 for( const auto& rPolyPolygon : rPolyPolygons )
327 {
328 glBeginepoxy_glBegin(GL_TRIANGLES0x0004);
329 renderComplexPolyPolygon( rPolyPolygon );
330 glEndepoxy_glEnd();
331 }
332
333 glLoadIdentityepoxy_glLoadIdentity();
334 glMatrixModeepoxy_glMatrixMode(GL_MODELVIEW0x1700);
335
336 glBindTextureepoxy_glBindTexture(GL_TEXTURE_2D0x0DE1, 0);
337 glDisableepoxy_glDisable(GL_TEXTURE_2D0x0DE1);
338
339 return true;
340 }
341 }
342
343 CanvasHelper::CanvasHelper() :
344 mpDevice( nullptr ),
345 mpDeviceHelper( nullptr ),
346 mpRecordedActions()
347 {}
348
349 CanvasHelper::~CanvasHelper()
350 {}
351
352 CanvasHelper& CanvasHelper::operator=( const CanvasHelper& rSrc )
353 {
354 mpDevice = rSrc.mpDevice;
355 mpDeviceHelper = rSrc.mpDeviceHelper;
356 mpRecordedActions = rSrc.mpRecordedActions;
357 return *this;
358 }
359
360 void CanvasHelper::disposing()
361 {
362 RecordVectorT aThrowaway;
363 mpRecordedActions.swap( aThrowaway );
364 mpDevice = nullptr;
365 mpDeviceHelper = nullptr;
366 }
367
368 void CanvasHelper::init( rendering::XGraphicDevice& rDevice,
369 SpriteDeviceHelper& rDeviceHelper )
370 {
371 mpDevice = &rDevice;
372 mpDeviceHelper = &rDeviceHelper;
373 }
374
375 void CanvasHelper::clear()
376 {
377 mpRecordedActions->clear();
378 }
379
380 void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
381 const geometry::RealPoint2D& aStartPoint,
382 const geometry::RealPoint2D& aEndPoint,
383 const rendering::ViewState& viewState,
384 const rendering::RenderState& renderState )
385 {
386 if( mpDevice )
387 {
388 mpRecordedActions->push_back( Action() );
389 Action& rAct=mpRecordedActions->back();
390
391 setupGraphicsState( rAct, viewState, renderState );
392 rAct.maFunction = std::bind(&lcl_drawLine,
393 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5,
394 aStartPoint, aEndPoint);
395 }
396 }
397
398 void CanvasHelper::drawBezier( const rendering::XCanvas* /*pCanvas*/,
399 const geometry::RealBezierSegment2D& aBezierSegment,
400 const geometry::RealPoint2D& aEndPoint,
401 const rendering::ViewState& viewState,
402 const rendering::RenderState& renderState )
403 {
404 if( !mpDevice )
405 return;
406
407 mpRecordedActions->push_back( Action() );
408 Action& rAct=mpRecordedActions->back();
409
410 setupGraphicsState( rAct, viewState, renderState );
411
412 // TODO(F2): subdivide&render whole curve
413 rAct.maFunction = std::bind(&lcl_drawLine,
414 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5,
415 geometry::RealPoint2D(
416 aBezierSegment.Px,
417 aBezierSegment.Py),
418 aEndPoint);
419 }
420
421 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
422 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
423 const rendering::ViewState& viewState,
424 const rendering::RenderState& renderState )
425 {
426 ENSURE_OR_THROW( xPolyPolygon.is(),if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "427" ": "), "%s", "CanvasHelper::drawPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
427 "CanvasHelper::drawPolyPolygon: polygon is NULL")if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "427" ": "), "%s", "CanvasHelper::drawPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
428
429 if( mpDevice )
430 {
431 mpRecordedActions->push_back( Action() );
432 Action& rAct=mpRecordedActions->back();
433
434 setupGraphicsState( rAct, viewState, renderState );
435 rAct.maPolyPolys.push_back(
436 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
437 rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
438
439 rAct.maFunction = &lcl_drawPolyPolygon;
440 }
441
442 // TODO(P1): Provide caching here.
443 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
444 }
445
446 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* /*pCanvas*/,
447 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
448 const rendering::ViewState& viewState,
449 const rendering::RenderState& renderState,
450 const rendering::StrokeAttributes& /*strokeAttributes*/ )
451 {
452 ENSURE_OR_THROW( xPolyPolygon.is(),if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "453" ": "), "%s", "CanvasHelper::strokePolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::strokePolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
453 "CanvasHelper::strokePolyPolygon: polygon is NULL")if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "453" ": "), "%s", "CanvasHelper::strokePolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::strokePolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
454
455 if( mpDevice )
456 {
457 mpRecordedActions->push_back( Action() );
458 Action& rAct=mpRecordedActions->back();
459
460 setupGraphicsState( rAct, viewState, renderState );
461 rAct.maPolyPolys.push_back(
462 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
463 rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
464
465 // TODO(F3): fallback to drawPolyPolygon currently
466 rAct.maFunction = &lcl_drawPolyPolygon;
467 }
468
469 // TODO(P1): Provide caching here.
470 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
471 }
472
473 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
474 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
475 const rendering::ViewState& /*viewState*/,
476 const rendering::RenderState& /*renderState*/,
477 const uno::Sequence< rendering::Texture >& /*textures*/,
478 const rendering::StrokeAttributes& /*strokeAttributes*/ )
479 {
480 // TODO
481 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
482 }
483
484 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
485 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
486 const rendering::ViewState& /*viewState*/,
487 const rendering::RenderState& /*renderState*/,
488 const uno::Sequence< rendering::Texture >& /*textures*/,
489 const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
490 const rendering::StrokeAttributes& /*strokeAttributes*/ )
491 {
492 // TODO
493 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
494 }
495
496 uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* /*pCanvas*/,
497 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
498 const rendering::ViewState& /*viewState*/,
499 const rendering::RenderState& /*renderState*/,
500 const rendering::StrokeAttributes& /*strokeAttributes*/ )
501 {
502 // TODO
503 return uno::Reference< rendering::XPolyPolygon2D >(nullptr);
504 }
505
506 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
507 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
508 const rendering::ViewState& viewState,
509 const rendering::RenderState& renderState )
510 {
511 ENSURE_OR_THROW( xPolyPolygon.is(),if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "512" ": "), "%s", "CanvasHelper::fillPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
512 "CanvasHelper::fillPolyPolygon: polygon is NULL")if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "512" ": "), "%s", "CanvasHelper::fillPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
513
514 if( mpDevice )
515 {
516 mpRecordedActions->push_back( Action() );
517 Action& rAct=mpRecordedActions->back();
518
519 setupGraphicsState( rAct, viewState, renderState );
520 rAct.maPolyPolys.push_back(
521 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
522 rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
523
524 rAct.maFunction = &lcl_fillPolyPolygon;
525 }
526
527 // TODO(P1): Provide caching here.
528 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
529 }
530
531 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
532 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
533 const rendering::ViewState& viewState,
534 const rendering::RenderState& renderState,
535 const uno::Sequence< rendering::Texture >& textures )
536 {
537 ENSURE_OR_THROW( xPolyPolygon.is(),if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "538" ": "), "%s", "CanvasHelper::fillPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
538 "CanvasHelper::fillPolyPolygon: polygon is NULL")if( !(xPolyPolygon.is()) ){ do { if (true && (!(xPolyPolygon
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "538" ": "), "%s", "CanvasHelper::fillPolyPolygon: polygon is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillPolyPolygon: polygon is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
539
540 if( mpDevice )
541 {
542 mpRecordedActions->push_back( Action() );
543 Action& rAct=mpRecordedActions->back();
544
545 setupGraphicsState( rAct, viewState, renderState );
546 rAct.maPolyPolys.push_back(
547 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon));
548 rAct.maPolyPolys.back().makeUnique(); // own copy, for thread safety
549
550 // TODO(F1): Multi-texturing
551 if( textures[0].Gradient.is() )
552 {
553 // try to cast XParametricPolyPolygon2D reference to
554 // our implementation class.
555 ::canvas::ParametricPolyPolygon* pGradient =
556 dynamic_cast< ::canvas::ParametricPolyPolygon* >( textures[0].Gradient.get() );
557
558 if( pGradient )
559 {
560 // copy state from Gradient polypoly locally
561 // (given object might change!)
562 const ::canvas::ParametricPolyPolygon::Values& rValues(
563 pGradient->getValues() );
564
565 rAct.maFunction = std::bind(&lcl_fillGradientPolyPolygon,
566 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4,
567 rValues,
568 textures[0],
569 std::placeholders::_6);
570 }
571 else
572 {
573 // TODO(F1): The generic case is missing here
574 ENSURE_OR_THROW( false,if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "575" ": "), "%s", "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered"
), css::uno::Reference< css::uno::XInterface >() ); }
575 "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered" )if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "575" ": "), "%s", "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::fillTexturedPolyPolygon(): unknown parametric polygon encountered"
), css::uno::Reference< css::uno::XInterface >() ); }
;
576 }
577 }
578 else if( textures[0].Bitmap.is() )
579 {
580 // own bitmap?
581 CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(textures[0].Bitmap.get());
582 if( pOwnBitmap )
583 {
584 // TODO(F2): own texture bitmap
585 }
586 else
587 {
588 // TODO(P3): Highly inefficient - simply copies pixel data
589
590 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
591 textures[0].Bitmap,
592 uno::UNO_QUERY);
593 if( xIntegerBitmap.is() )
594 {
595 const geometry::IntegerSize2D aSize=xIntegerBitmap->getSize();
596 rendering::IntegerBitmapLayout aLayout;
597 uno::Sequence<sal_Int8> aPixelData=
598 xIntegerBitmap->getData(
599 aLayout,
600 geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
601
602 // force-convert color to ARGB8888 int color space
603 uno::Sequence<sal_Int8> aARGBBytes(
604 aLayout.ColorSpace->convertToIntegerColorSpace(
605 aPixelData,
606 canvas::tools::getStdColorSpace()));
607
608 rAct.maFunction = std::bind(&lcl_fillTexturedPolyPolygon,
609 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4,
610 textures[0],
611 aSize,
612 aARGBBytes,
613 rtl_crc32(0,
614 aARGBBytes.getConstArray(),
615 aARGBBytes.getLength()),
616 std::placeholders::_6);
617 }
618 // TODO(F1): handle non-integer case
619 }
620 }
621 }
622
623 // TODO(P1): Provide caching here.
624 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
625 }
626
627 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* /*pCanvas*/,
628 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
629 const rendering::ViewState& /*viewState*/,
630 const rendering::RenderState& /*renderState*/,
631 const uno::Sequence< rendering::Texture >& /*textures*/,
632 const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
633 {
634 // TODO
635 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
636 }
637
638 uno::Reference< rendering::XCanvasFont > CanvasHelper::createFont( const rendering::XCanvas* /*pCanvas*/,
639 const rendering::FontRequest& fontRequest,
640 const uno::Sequence< beans::PropertyValue >& extraFontProperties,
641 const geometry::Matrix2D& fontMatrix )
642 {
643 if( mpDevice )
644 return uno::Reference< rendering::XCanvasFont >(
645 new CanvasFont(fontRequest, extraFontProperties, fontMatrix ) );
646
647 return uno::Reference< rendering::XCanvasFont >();
648 }
649
650 uno::Sequence< rendering::FontInfo > CanvasHelper::queryAvailableFonts( const rendering::XCanvas* /*pCanvas*/,
651 const rendering::FontInfo& /*aFilter*/,
652 const uno::Sequence< beans::PropertyValue >& /*aFontProperties*/ )
653 {
654 // TODO
655 return uno::Sequence< rendering::FontInfo >();
656 }
657
658 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas* /*pCanvas*/,
659 const rendering::StringContext& /*text*/,
660 const uno::Reference< rendering::XCanvasFont >& /*xFont*/,
661 const rendering::ViewState& /*viewState*/,
662 const rendering::RenderState& /*renderState*/,
663 sal_Int8 /*textDirection*/ )
664 {
665 // TODO - but not used from slideshow
666 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
667 }
668
669 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawTextLayout( const rendering::XCanvas* /*pCanvas*/,
670 const uno::Reference< rendering::XTextLayout >& xLayoutetText,
671 const rendering::ViewState& viewState,
672 const rendering::RenderState& renderState )
673 {
674 ENSURE_OR_THROW( xLayoutetText.is(),if( !(xLayoutetText.is()) ){ do { if (true && (!(xLayoutetText
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "675" ": "), "%s", "CanvasHelper::drawTextLayout: text is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawTextLayout: text is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
1
Taking false branch
675 "CanvasHelper::drawTextLayout: text is NULL")if( !(xLayoutetText.is()) ){ do { if (true && (!(xLayoutetText
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "675" ": "), "%s", "CanvasHelper::drawTextLayout: text is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawTextLayout: text is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
676
677 if( mpDevice )
2
Assuming field 'mpDevice' is non-null
3
Taking true branch
678 {
679 ScopedVclPtrInstance< VirtualDevice > pVDev;
4
Calling default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
6
Returning from default constructor for 'ScopedVclPtrInstance<VirtualDevice>'
680 pVDev->EnableOutput(false);
681
682 CanvasFont* pFont=dynamic_cast<CanvasFont*>(xLayoutetText->getFont().get());
683 const rendering::StringContext& rTxt=xLayoutetText->getText();
684 if( pFont
6.1
'pFont' is null
6.1
'pFont' is null
6.1
'pFont' is null
6.1
'pFont' is null
&& rTxt.Length )
685 {
686 // create the font
687 const rendering::FontRequest& rFontRequest = pFont->getFontRequest();
688 const geometry::Matrix2D& rFontMatrix = pFont->getFontMatrix();
689 vcl::Font aFont(
690 rFontRequest.FontDescription.FamilyName,
691 rFontRequest.FontDescription.StyleName,
692 Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
693
694 aFont.SetAlignment( ALIGN_BASELINE );
695 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL(((rtl_TextEncoding) 10)) : RTL_TEXTENCODING_UNICODE(((rtl_TextEncoding) 0xFFFF)) );
696 aFont.SetVertical( rFontRequest.FontDescription.IsVertical==util::TriState_YES );
697 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
698 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
699
700 if (pFont->getEmphasisMark())
701 aFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark()));
702
703 // adjust to stretched font
704 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
705 {
706 const Size aSize = pVDev->GetFontMetric( aFont ).GetFontSize();
707 const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
708 double fStretch = rFontMatrix.m00 + rFontMatrix.m01;
709
710 if( !::basegfx::fTools::equalZero( fDividend) )
711 fStretch /= fDividend;
712
713 const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
714
715 aFont.SetAverageFontWidth( nNewWidth );
716 }
717
718 // set font
719 pVDev->SetFont(aFont);
720
721 mpRecordedActions->push_back( Action() );
722 Action& rAct=mpRecordedActions->back();
723
724 setupGraphicsState( rAct, viewState, renderState );
725
726 // handle custom spacing, if there
727 uno::Sequence<double> aLogicalAdvancements=xLayoutetText->queryLogicalAdvancements();
728 if( aLogicalAdvancements.hasElements() )
729 {
730 // create the DXArray
731 const sal_Int32 nLen( aLogicalAdvancements.getLength() );
732 std::unique_ptr<long[]> pDXArray( new long[nLen] );
733 for( sal_Int32 i=0; i<nLen; ++i )
734 pDXArray[i] = basegfx::fround( aLogicalAdvancements[i] );
735
736 // get the glyphs
737 pVDev->GetTextOutlines(rAct.maPolyPolys,
738 rTxt.Text,
739 0,
740 rTxt.StartPosition,
741 rTxt.Length,
742 0,
743 pDXArray.get() );
744 }
745 else
746 {
747 // get the glyphs
748 pVDev->GetTextOutlines(rAct.maPolyPolys,
749 rTxt.Text,
750 0,
751 rTxt.StartPosition,
752 rTxt.Length );
753 }
754
755 // own copy, for thread safety
756 for( auto& rPoly : rAct.maPolyPolys )
757 rPoly.makeUnique();
758
759 rAct.maFunction = &lcl_fillPolyPolygon;
760 }
761 }
7
Calling implicit destructor for 'ScopedVclPtrInstance<VirtualDevice>'
8
Calling '~ScopedVclPtr'
762
763 // TODO
764 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
765 }
766
767 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* /*pCanvas*/,
768 const uno::Reference< rendering::XBitmap >& xBitmap,
769 const rendering::ViewState& viewState,
770 const rendering::RenderState& renderState )
771 {
772 ENSURE_OR_THROW( xBitmap.is(),if( !(xBitmap.is()) ){ do { if (true && (!(xBitmap.is
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "773" ": "), "%s", "CanvasHelper::drawBitmap: bitmap is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawBitmap: bitmap is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
773 "CanvasHelper::drawBitmap: bitmap is NULL")if( !(xBitmap.is()) ){ do { if (true && (!(xBitmap.is
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "773" ": "), "%s", "CanvasHelper::drawBitmap: bitmap is NULL"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::drawBitmap: bitmap is NULL"
), css::uno::Reference< css::uno::XInterface >() ); }
;
774
775 if( mpDevice )
776 {
777 // own bitmap?
778 CanvasBitmap* pOwnBitmap=dynamic_cast<CanvasBitmap*>(xBitmap.get());
779 if( pOwnBitmap )
780 {
781 // insert as transformed copy of bitmap action vector -
782 // during rendering, this gets rendered into a temporary
783 // buffer, and then composited to the front
784 mpRecordedActions->push_back( Action() );
785 Action& rAct=mpRecordedActions->back();
786
787 setupGraphicsState( rAct, viewState, renderState );
788 rAct.maFunction = std::bind(&lcl_drawOwnBitmap,
789 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5,
790 *pOwnBitmap);
791 }
792 else
793 {
794 // TODO(P3): Highly inefficient - simply copies pixel data
795
796 uno::Reference< rendering::XIntegerReadOnlyBitmap > xIntegerBitmap(
797 xBitmap, uno::UNO_QUERY);
798 if( xIntegerBitmap.is() )
799 {
800 const geometry::IntegerSize2D aSize=xBitmap->getSize();
801 rendering::IntegerBitmapLayout aLayout;
802 uno::Sequence<sal_Int8> aPixelData=
803 xIntegerBitmap->getData(
804 aLayout,
805 geometry::IntegerRectangle2D(0,0,aSize.Width,aSize.Height));
806
807 // force-convert color to ARGB8888 int color space
808 uno::Sequence<sal_Int8> aARGBBytes(
809 aLayout.ColorSpace->convertToIntegerColorSpace(
810 aPixelData,
811 canvas::tools::getStdColorSpace()));
812
813 mpRecordedActions->push_back( Action() );
814 Action& rAct=mpRecordedActions->back();
815
816 setupGraphicsState( rAct, viewState, renderState );
817 rAct.maFunction = std::bind(&lcl_drawGenericBitmap,
818 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5,
819 aSize, aARGBBytes,
820 rtl_crc32(0,
821 aARGBBytes.getConstArray(),
822 aARGBBytes.getLength()));
823 }
824 // TODO(F1): handle non-integer case
825 }
826 }
827
828 // TODO(P1): Provide caching here.
829 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
830 }
831
832 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
833 const uno::Reference< rendering::XBitmap >& xBitmap,
834 const rendering::ViewState& viewState,
835 const rendering::RenderState& renderState )
836 {
837 // TODO(F3): remove this wart altogether
838 return drawBitmap(pCanvas, xBitmap, viewState, renderState);
839 }
840
841
842 void CanvasHelper::setupGraphicsState( Action& o_action,
843 const rendering::ViewState& viewState,
844 const rendering::RenderState& renderState )
845 {
846 ENSURE_OR_THROW( mpDevice,if( !(mpDevice) ){ do { if (true && (!(mpDevice))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "847" ": "), "%s", "CanvasHelper::setupGraphicsState: reference device invalid"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::setupGraphicsState: reference device invalid"
), css::uno::Reference< css::uno::XInterface >() ); }
847 "CanvasHelper::setupGraphicsState: reference device invalid" )if( !(mpDevice) ){ do { if (true && (!(mpDevice))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "847" ": "), "%s", "CanvasHelper::setupGraphicsState: reference device invalid"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::setupGraphicsState: reference device invalid"
), css::uno::Reference< css::uno::XInterface >() ); }
;
848
849 // TODO(F3): clipping
850 // TODO(P2): think about caching transformations between canvas calls
851
852 // setup overall transform only now. View clip above was
853 // relative to view transform
854 ::canvas::tools::mergeViewAndRenderTransform(o_action.maTransform,
855 viewState,
856 renderState);
857 // setup compositing - mapping courtesy David Reveman
858 // (glitz_operator.c)
859 switch( renderState.CompositeOperation )
860 {
861 case rendering::CompositeOperation::OVER:
862 o_action.meSrcBlendMode=GL_ONE1;
863 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA0x0303;
864 break;
865 case rendering::CompositeOperation::CLEAR:
866 o_action.meSrcBlendMode=GL_ZERO0;
867 o_action.meDstBlendMode=GL_ZERO0;
868 break;
869 case rendering::CompositeOperation::SOURCE:
870 o_action.meSrcBlendMode=GL_ONE1;
871 o_action.meDstBlendMode=GL_ZERO0;
872 break;
873 case rendering::CompositeOperation::UNDER:
874 case rendering::CompositeOperation::DESTINATION:
875 o_action.meSrcBlendMode=GL_ZERO0;
876 o_action.meDstBlendMode=GL_ONE1;
877 break;
878 case rendering::CompositeOperation::INSIDE:
879 o_action.meSrcBlendMode=GL_DST_ALPHA0x0304;
880 o_action.meDstBlendMode=GL_ZERO0;
881 break;
882 case rendering::CompositeOperation::INSIDE_REVERSE:
883 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA0x0305;
884 o_action.meDstBlendMode=GL_ZERO0;
885 break;
886 case rendering::CompositeOperation::OUTSIDE:
887 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA0x0305;
888 o_action.meDstBlendMode=GL_ONE1;
889 break;
890 case rendering::CompositeOperation::OUTSIDE_REVERSE:
891 o_action.meSrcBlendMode=GL_ZERO0;
892 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA0x0303;
893 break;
894 case rendering::CompositeOperation::ATOP:
895 o_action.meSrcBlendMode=GL_DST_ALPHA0x0304;
896 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA0x0303;
897 break;
898 case rendering::CompositeOperation::ATOP_REVERSE:
899 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA0x0305;
900 o_action.meDstBlendMode=GL_SRC_ALPHA0x0302;
901 break;
902 case rendering::CompositeOperation::XOR:
903 o_action.meSrcBlendMode=GL_ONE_MINUS_DST_ALPHA0x0305;
904 o_action.meDstBlendMode=GL_ONE_MINUS_SRC_ALPHA0x0303;
905 break;
906 case rendering::CompositeOperation::ADD:
907 o_action.meSrcBlendMode=GL_ONE1;
908 o_action.meDstBlendMode=GL_ONE1;
909 break;
910 case rendering::CompositeOperation::SATURATE:
911 o_action.meSrcBlendMode=GL_SRC_ALPHA_SATURATE0x0308;
912 o_action.meDstBlendMode=GL_SRC_ALPHA_SATURATE0x0308;
913 break;
914
915 default:
916 ENSURE_OR_THROW( false, "CanvasHelper::setupGraphicsState: unexpected mode" )if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/opengl/ogl_canvashelper.cxx"
":" "916" ": "), "%s", "CanvasHelper::setupGraphicsState: unexpected mode"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "CanvasHelper::setupGraphicsState: unexpected mode"
), css::uno::Reference< css::uno::XInterface >() ); }
;
917 break;
918 }
919
920 if (renderState.DeviceColor.hasElements())
921 o_action.maARGBColor =
922 mpDevice->getDeviceColorSpace()->convertToARGB(renderState.DeviceColor)[0];
923 }
924
925 bool CanvasHelper::renderRecordedActions() const
926 {
927 for( const auto& rRecordedAction : *mpRecordedActions )
928 {
929 if( !rRecordedAction.maFunction( *this,
930 rRecordedAction.maTransform,
931 rRecordedAction.meSrcBlendMode,
932 rRecordedAction.meDstBlendMode,
933 rRecordedAction.maARGBColor,
934 rRecordedAction.maPolyPolys ) )
935 return false;
936 }
937
938 return true;
939 }
940
941 size_t CanvasHelper::getRecordedActionCount() const
942 {
943 return mpRecordedActions->size();
944 }
945}
946
947/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
10
Calling 'Reference::clear'
17
Returning; memory was released
205 if (aTmp.get()) {
18
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();
9
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
5
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

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