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 cairo_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 -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/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/cairo/cairo_canvashelper.cxx

/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_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 * 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 <sal/config.h>
21#include <sal/log.hxx>
22
23#include <algorithm>
24#include <tuple>
25
26#include <basegfx/point/b2dpoint.hxx>
27#include <basegfx/polygon/b2dpolygon.hxx>
28#include <basegfx/polygon/b2dpolypolygon.hxx>
29#include <basegfx/utils/canvastools.hxx>
30#include <basegfx/utils/keystoplerp.hxx>
31#include <basegfx/utils/lerp.hxx>
32#include <com/sun/star/rendering/ColorComponentTag.hpp>
33#include <com/sun/star/rendering/ColorSpaceType.hpp>
34#include <com/sun/star/rendering/CompositeOperation.hpp>
35#include <com/sun/star/rendering/IntegerBitmapLayout.hpp>
36#include <com/sun/star/rendering/PathCapType.hpp>
37#include <com/sun/star/rendering/PathJoinType.hpp>
38#include <com/sun/star/rendering/RenderingIntent.hpp>
39#include <com/sun/star/rendering/TexturingMode.hpp>
40#include <com/sun/star/rendering/XIntegerBitmapColorSpace.hpp>
41#include <com/sun/star/util/Endianness.hpp>
42#include <comphelper/sequence.hxx>
43#include <cppuhelper/implbase.hxx>
44#include <rtl/instance.hxx>
45#include <rtl/math.hxx>
46#include <tools/diagnose_ex.h>
47#include <vcl/bitmapex.hxx>
48#include <vcl/BitmapTools.hxx>
49#include <vcl/canvastools.hxx>
50#include <vcl/virdev.hxx>
51
52#include <canvas/canvastools.hxx>
53#include <parametricpolypolygon.hxx>
54#include <cairo.h>
55
56#include "cairo_cachedbitmap.hxx"
57#include "cairo_canvasbitmap.hxx"
58#include "cairo_canvashelper.hxx"
59
60using namespace ::cairo;
61using namespace ::com::sun::star;
62
63namespace cairocanvas
64{
65 CanvasHelper::CanvasHelper() :
66 mpSurfaceProvider(nullptr),
67 mpDevice(nullptr),
68 mpVirtualDevice(),
69 mbHaveAlpha(),
70 mpCairo(),
71 mpSurface(),
72 maSize()
73 {
74 }
75
76 void CanvasHelper::disposing()
77 {
78 mpSurface.reset();
79 mpCairo.reset();
80 mpVirtualDevice.disposeAndClear();
81 mpDevice = nullptr;
82 mpSurfaceProvider = nullptr;
83 }
84
85 void CanvasHelper::init( const ::basegfx::B2ISize& rSizePixel,
86 SurfaceProvider& rSurfaceProvider,
87 rendering::XGraphicDevice* pDevice )
88 {
89 maSize = rSizePixel;
90 mpSurfaceProvider = &rSurfaceProvider;
91 mpDevice = pDevice;
92 }
93
94 void CanvasHelper::setSize( const ::basegfx::B2ISize& rSize )
95 {
96 maSize = rSize;
97 }
98
99 void CanvasHelper::setSurface( const SurfaceSharedPtr& pSurface, bool bHasAlpha )
100 {
101 mbHaveAlpha = bHasAlpha;
102 mpVirtualDevice.disposeAndClear();
1
Calling 'VclPtr::disposeAndClear'
103 mpSurface = pSurface;
104 mpCairo = pSurface->getCairo();
105 }
106
107 static void setColor( cairo_t* pCairo,
108 const uno::Sequence<double>& rColor )
109 {
110 if( rColor.getLength() > 3 )
111 {
112 cairo_set_source_rgba( pCairo,
113 rColor[0],
114 rColor[1],
115 rColor[2],
116 rColor[3] );
117 }
118 else if( rColor.getLength() == 3 )
119 cairo_set_source_rgb( pCairo,
120 rColor[0],
121 rColor[1],
122 rColor[2] );
123 }
124
125 void CanvasHelper::useStates( const rendering::ViewState& viewState,
126 const rendering::RenderState& renderState,
127 bool bSetColor )
128 {
129 cairo_matrix_t aViewMatrix;
130 cairo_matrix_t aRenderMatrix;
131 cairo_matrix_t aCombinedMatrix;
132
133 cairo_matrix_init( &aViewMatrix,
134 viewState.AffineTransform.m00, viewState.AffineTransform.m10, viewState.AffineTransform.m01,
135 viewState.AffineTransform.m11, viewState.AffineTransform.m02, viewState.AffineTransform.m12);
136 cairo_matrix_init( &aRenderMatrix,
137 renderState.AffineTransform.m00, renderState.AffineTransform.m10, renderState.AffineTransform.m01,
138 renderState.AffineTransform.m11, renderState.AffineTransform.m02, renderState.AffineTransform.m12);
139 cairo_matrix_multiply( &aCombinedMatrix, &aRenderMatrix, &aViewMatrix);
140
141 if( viewState.Clip.is() )
142 {
143 SAL_INFO( "canvas.cairo", "view clip")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "view clip") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "143" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "view clip"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "view clip"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "143" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "view clip") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "143" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "view clip"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "view clip"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "143" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
144
145 aViewMatrix.x0 = basegfx::fround( aViewMatrix.x0 );
146 aViewMatrix.y0 = basegfx::fround( aViewMatrix.y0 );
147 cairo_set_matrix( mpCairo.get(), &aViewMatrix );
148 doPolyPolygonPath( viewState.Clip, Clip );
149 }
150
151 aCombinedMatrix.x0 = basegfx::fround( aCombinedMatrix.x0 );
152 aCombinedMatrix.y0 = basegfx::fround( aCombinedMatrix.y0 );
153 cairo_set_matrix( mpCairo.get(), &aCombinedMatrix );
154
155 if( renderState.Clip.is() )
156 {
157 SAL_INFO( "canvas.cairo", "render clip BEGIN")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "render clip BEGIN") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "157" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "render clip BEGIN"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"render clip BEGIN"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "157" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "render clip BEGIN") == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "157" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "render clip BEGIN"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"render clip BEGIN"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "157" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
158
159 doPolyPolygonPath( renderState.Clip, Clip );
160 SAL_INFO( "canvas.cairo", "render clip END")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "render clip END") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "160" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "render clip END"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"render clip END"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "160" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "render clip END") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "160" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "render clip END"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"render clip END"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "160" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
161 }
162
163 if( bSetColor )
164 setColor(mpCairo.get(),renderState.DeviceColor);
165
166 cairo_operator_t compositingMode( CAIRO_OPERATOR_OVER );
167 switch( renderState.CompositeOperation )
168 {
169 case rendering::CompositeOperation::CLEAR:
170 compositingMode = CAIRO_OPERATOR_CLEAR;
171 break;
172 case rendering::CompositeOperation::SOURCE:
173 compositingMode = CAIRO_OPERATOR_SOURCE;
174 break;
175 case rendering::CompositeOperation::DESTINATION:
176 compositingMode = CAIRO_OPERATOR_DEST;
177 break;
178 case rendering::CompositeOperation::OVER:
179 compositingMode = CAIRO_OPERATOR_OVER;
180 break;
181 case rendering::CompositeOperation::UNDER:
182 compositingMode = CAIRO_OPERATOR_DEST;
183 break;
184 case rendering::CompositeOperation::INSIDE:
185 compositingMode = CAIRO_OPERATOR_IN;
186 break;
187 case rendering::CompositeOperation::INSIDE_REVERSE:
188 compositingMode = CAIRO_OPERATOR_OUT;
189 break;
190 case rendering::CompositeOperation::OUTSIDE:
191 compositingMode = CAIRO_OPERATOR_DEST_OVER;
192 break;
193 case rendering::CompositeOperation::OUTSIDE_REVERSE:
194 compositingMode = CAIRO_OPERATOR_DEST_OUT;
195 break;
196 case rendering::CompositeOperation::ATOP:
197 compositingMode = CAIRO_OPERATOR_ATOP;
198 break;
199 case rendering::CompositeOperation::ATOP_REVERSE:
200 compositingMode = CAIRO_OPERATOR_DEST_ATOP;
201 break;
202 case rendering::CompositeOperation::XOR:
203 compositingMode = CAIRO_OPERATOR_XOR;
204 break;
205 case rendering::CompositeOperation::ADD:
206 compositingMode = CAIRO_OPERATOR_ADD;
207 break;
208 case rendering::CompositeOperation::SATURATE:
209 compositingMode = CAIRO_OPERATOR_SATURATE;
210 break;
211 }
212 cairo_set_operator( mpCairo.get(), compositingMode );
213 }
214
215 void CanvasHelper::clear()
216 {
217 SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getX() << " x " << maSize.getY() )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "clear whole area: " <<
maSize.getX() << " x " << maSize.getY()) == 1) {
::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "217" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clear whole area: " << maSize.getX
() << " x " << maSize.getY()), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"clear whole area: " << maSize.getX() << " x " <<
maSize.getY(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "217" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "clear whole area: " << maSize.getX() <<
" x " << maSize.getY()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "217" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clear whole area: " << maSize.getX
() << " x " << maSize.getY()), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"clear whole area: " << maSize.getX() << " x " <<
maSize.getY(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "217" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
218
219 if( !mpCairo )
220 return;
221
222 cairo_save( mpCairo.get() );
223
224 cairo_identity_matrix( mpCairo.get() );
225 // this does not really differ from all-zero, as cairo
226 // internally converts to premultiplied alpha. but anyway,
227 // this keeps it consistent with the other canvas impls
228 if( mbHaveAlpha )
229 cairo_set_source_rgba( mpCairo.get(), 1.0, 1.0, 1.0, 0.0 );
230 else
231 cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 );
232 cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
233
234 cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
235 cairo_fill( mpCairo.get() );
236
237 cairo_restore( mpCairo.get() );
238 }
239
240 void CanvasHelper::drawLine( const rendering::XCanvas* /*pCanvas*/,
241 const geometry::RealPoint2D& aStartPoint,
242 const geometry::RealPoint2D& aEndPoint,
243 const rendering::ViewState& viewState,
244 const rendering::RenderState& renderState )
245 {
246 if( !mpCairo )
247 return;
248
249 cairo_save( mpCairo.get() );
250
251 cairo_set_line_width( mpCairo.get(), 1 );
252
253 useStates( viewState, renderState, true );
254
255 cairo_move_to( mpCairo.get(), aStartPoint.X + 0.5, aStartPoint.Y + 0.5 );
256 cairo_line_to( mpCairo.get(), aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
257 cairo_stroke( mpCairo.get() );
258
259 cairo_restore( mpCairo.get() );
260 }
261
262 void CanvasHelper::drawBezier( const rendering::XCanvas* ,
263 const geometry::RealBezierSegment2D& aBezierSegment,
264 const geometry::RealPoint2D& aEndPoint,
265 const rendering::ViewState& viewState,
266 const rendering::RenderState& renderState )
267 {
268 if( !mpCairo )
269 return;
270
271 cairo_save( mpCairo.get() );
272
273 cairo_set_line_width( mpCairo.get(), 1 );
274
275 useStates( viewState, renderState, true );
276
277 cairo_move_to( mpCairo.get(), aBezierSegment.Px + 0.5, aBezierSegment.Py + 0.5 );
278 // tdf#99165 correction of control points not needed here, only hairlines drawn
279 // (see cairo_set_line_width above)
280 cairo_curve_to( mpCairo.get(),
281 aBezierSegment.C1x + 0.5, aBezierSegment.C1y + 0.5,
282 aBezierSegment.C2x + 0.5, aBezierSegment.C2y + 0.5,
283 aEndPoint.X + 0.5, aEndPoint.Y + 0.5 );
284 cairo_stroke( mpCairo.get() );
285
286 cairo_restore( mpCairo.get() );
287 }
288
289#define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME"Canvas::ParametricPolyPolygon" "Canvas::ParametricPolyPolygon"
290
291 /** surfaceFromXBitmap Create a surface from XBitmap
292 * @param xBitmap bitmap image that will be used for the surface
293 * @param bHasAlpha will be set to true if resulting surface has alpha
294 *
295 * This is a helper function for the other surfaceFromXBitmap().
296 * This function tries to create surface from xBitmap by checking if xBitmap is CanvasBitmap or SpriteCanvas.
297 *
298 * @return created surface or NULL
299 **/
300 static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
301 {
302 CanvasBitmap* pBitmapImpl = dynamic_cast< CanvasBitmap* >( xBitmap.get() );
303 if( pBitmapImpl )
304 return pBitmapImpl->getSurface();
305
306 SurfaceProvider* pSurfaceProvider = dynamic_cast<SurfaceProvider*>( xBitmap.get() );
307 if( pSurfaceProvider )
308 return pSurfaceProvider->getSurface();
309
310 return SurfaceSharedPtr();
311 }
312
313 static ::BitmapEx bitmapExFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap )
314 {
315 // TODO(F1): Add support for floating point bitmap formats
316 uno::Reference<rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap,
317 uno::UNO_QUERY_THROW);
318 ::BitmapEx aBmpEx = vcl::unotools::bitmapExFromXBitmap(xIntBmp);
319 if( !!aBmpEx )
320 return aBmpEx;
321
322 // TODO(F1): extract pixel from XBitmap interface
323 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/cairo/cairo_canvashelper.cxx"
":" "324" ": "), "%s", "bitmapExFromXBitmap(): could not extract BitmapEx"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "bitmapExFromXBitmap(): could not extract BitmapEx"
), css::uno::Reference< css::uno::XInterface >() ); }
324 "bitmapExFromXBitmap(): could not extract BitmapEx" )if( !(false) ){ do { if (true && (!(false))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "324" ": "), "%s", "bitmapExFromXBitmap(): could not extract BitmapEx"
); } } while (false); throw css::uno::RuntimeException( __func__
+ OUStringLiteral(u",\n" "bitmapExFromXBitmap(): could not extract BitmapEx"
), css::uno::Reference< css::uno::XInterface >() ); }
;
325
326 return ::BitmapEx();
327 }
328
329 /** surfaceFromXBitmap Create a surface from XBitmap
330 * @param xBitmap bitmap image that will be used for the surface
331 * @param rDevice reference to the device into which we want to draw
332 * @param data will be filled with alpha data, if xBitmap is alpha/transparent image
333 * @param bHasAlpha will be set to true if resulting surface has alpha
334 *
335 * This function tries various methods for creating a surface from xBitmap. It also uses
336 * the helper function surfaceFromXBitmap( xBitmap, bHasAlpha )
337 *
338 * @return created surface or NULL
339 **/
340 static SurfaceSharedPtr surfaceFromXBitmap( const uno::Reference< rendering::XBitmap >& xBitmap, const SurfaceProviderRef& rSurfaceProvider, unsigned char*& data, bool& bHasAlpha )
341 {
342 bHasAlpha = xBitmap->hasAlpha();
343 SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap );
344 if( pSurface )
345 data = nullptr;
346 else
347 {
348 ::BitmapEx aBmpEx = bitmapExFromXBitmap(xBitmap);
349 ::Bitmap aBitmap = aBmpEx.GetBitmap();
350
351 // there's no pixmap for alpha bitmap. we might still
352 // use rgb pixmap and only access alpha pixels the
353 // slow way. now we just speedup rgb bitmaps
354 if( !aBmpEx.IsTransparent() && !aBmpEx.IsAlpha() )
355 {
356 pSurface = rSurfaceProvider->createSurface( aBitmap );
357 data = nullptr;
358 bHasAlpha = false;
359 }
360
361 if( !pSurface )
362 {
363 long nWidth;
364 long nHeight;
365 vcl::bitmap::CanvasCairoExtractBitmapData(aBmpEx, aBitmap, data, bHasAlpha, nWidth, nHeight);
366
367 SurfaceSharedPtr pImageSurface = rSurfaceProvider->getOutputDevice()->CreateSurface(
368 CairoSurfaceSharedPtr(
369 cairo_image_surface_create_for_data(
370 data,
371 bHasAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24,
372 nWidth, nHeight, nWidth*4 ),
373 &cairo_surface_destroy) );
374 pSurface = pImageSurface;
375
376 SAL_INFO( "canvas.cairo","image: " << nWidth << " x " << nHeight << " alpha: " << bHasAlpha)do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "image: " << nWidth
<< " x " << nHeight << " alpha: " <<
bHasAlpha) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "376" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "image: " << nWidth << " x "
<< nHeight << " alpha: " << bHasAlpha), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "image: " << nWidth << " x " << nHeight
<< " alpha: " << bHasAlpha; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "376" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "image: " << nWidth << " x " <<
nHeight << " alpha: " << bHasAlpha) == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "376" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "image: " << nWidth << " x "
<< nHeight << " alpha: " << bHasAlpha), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "image: " << nWidth << " x " << nHeight
<< " alpha: " << bHasAlpha; ::sal::detail::log( (
::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "376" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
377 }
378 }
379
380 return pSurface;
381 }
382
383 static void addColorStops( cairo_pattern_t* pPattern, const uno::Sequence< uno::Sequence< double > >& rColors, const uno::Sequence< double >& rStops, bool bReverseStops )
384 {
385 int i;
386
387 OSL_ASSERT( rColors.getLength() == rStops.getLength() )do { if (true && (!(rColors.getLength() == rStops.getLength
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "387" ": "), "OSL_ASSERT: %s", "rColors.getLength() == rStops.getLength()"
); } } while (false)
;
388
389 for( i = 0; i < rColors.getLength(); i++ )
390 {
391 const uno::Sequence< double >& rColor( rColors[i] );
392 float stop = bReverseStops ? 1 - rStops[i] : rStops[i];
393 if( rColor.getLength() == 3 )
394 cairo_pattern_add_color_stop_rgb( pPattern, stop, rColor[0], rColor[1], rColor[2] );
395 else if( rColor.getLength() == 4 )
396 {
397 double alpha = rColor[3];
398 // cairo expects premultiplied alpha
399 cairo_pattern_add_color_stop_rgba( pPattern, stop, rColor[0]*alpha, rColor[1]*alpha, rColor[2]*alpha, alpha );
400 }
401 }
402 }
403
404 static uno::Sequence<double> lerp(const uno::Sequence<double>& rLeft, const uno::Sequence<double>& rRight, double fAlpha)
405 {
406 if( rLeft.getLength() == 3 )
407 {
408 uno::Sequence<double> aRes(3);
409 aRes[0] = basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha);
410 aRes[1] = basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha);
411 aRes[2] = basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha);
412 return aRes;
413 }
414 else if( rLeft.getLength() == 4 )
415 {
416 uno::Sequence<double> aRes(4);
417 aRes[0] = basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha);
418 aRes[1] = basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha);
419 aRes[2] = basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha);
420 aRes[3] = basegfx::utils::lerp(rLeft[3],rRight[3],fAlpha);
421 return aRes;
422 }
423
424 return uno::Sequence<double>();
425 }
426
427 static cairo_pattern_t* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon const & rPolygon )
428 {
429 cairo_pattern_t* pPattern = nullptr;
430 const ::canvas::ParametricPolyPolygon::Values aValues = rPolygon.getValues();
431 double x0, x1, y0, y1, cx, cy, r0, r1;
432
433 switch( aValues.meType )
434 {
435 case ::canvas::ParametricPolyPolygon::GradientType::Linear:
436 x0 = 0;
437 y0 = 0;
438 x1 = 1;
439 y1 = 0;
440 pPattern = cairo_pattern_create_linear( x0, y0, x1, y1 );
441 addColorStops( pPattern, aValues.maColors, aValues.maStops, false );
442 break;
443
444 case ::canvas::ParametricPolyPolygon::GradientType::Elliptical:
445 cx = 0;
446 cy = 0;
447 r0 = 0;
448 r1 = 1;
449
450 pPattern = cairo_pattern_create_radial( cx, cy, r0, cy, cy, r1 );
451 addColorStops( pPattern, aValues.maColors, aValues.maStops, true );
452 break;
453 default:
454 break;
455 }
456
457 return pPattern;
458 }
459
460 static void doOperation( Operation aOperation,
461 cairo_t* pCairo,
462 const uno::Sequence< rendering::Texture >* pTextures,
463 const SurfaceProviderRef& pDevice,
464 const basegfx::B2DRange& rBounds )
465 {
466 switch( aOperation )
467 {
468 case Fill:
469 /* TODO: multitexturing */
470 if( pTextures )
471 {
472 const css::rendering::Texture& aTexture ( (*pTextures)[0] );
473 if( aTexture.Bitmap.is() )
474 {
475 unsigned char* data = nullptr;
476 bool bHasAlpha = false;
477 SurfaceSharedPtr pSurface = surfaceFromXBitmap( (*pTextures)[0].Bitmap, pDevice, data, bHasAlpha );
478
479 if( pSurface )
480 {
481 cairo_pattern_t* pPattern;
482
483 cairo_save( pCairo );
484
485 css::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform );
486 cairo_matrix_t aScaleMatrix, aTextureMatrix, aScaledTextureMatrix;
487
488 cairo_matrix_init( &aTextureMatrix,
489 aTransform.m00, aTransform.m10, aTransform.m01,
490 aTransform.m11, aTransform.m02, aTransform.m12);
491
492 geometry::IntegerSize2D aSize = aTexture.Bitmap->getSize();
493
494 cairo_matrix_init_scale( &aScaleMatrix, 1.0/aSize.Width, 1.0/aSize.Height );
495 cairo_matrix_multiply( &aScaledTextureMatrix, &aTextureMatrix, &aScaleMatrix );
496 cairo_matrix_invert( &aScaledTextureMatrix );
497
498 // we don't care about repeat mode yet, so the workaround is disabled for now
499 pPattern = cairo_pattern_create_for_surface( pSurface->getCairoSurface().get() );
500
501 if( aTexture.RepeatModeX == rendering::TexturingMode::REPEAT &&
502 aTexture.RepeatModeY == rendering::TexturingMode::REPEAT )
503 {
504 cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_REPEAT );
505 }
506 else if ( aTexture.RepeatModeX == rendering::TexturingMode::NONE &&
507 aTexture.RepeatModeY == rendering::TexturingMode::NONE )
508 {
509 cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_NONE );
510 }
511 else if ( aTexture.RepeatModeX == rendering::TexturingMode::CLAMP &&
512 aTexture.RepeatModeY == rendering::TexturingMode::CLAMP )
513 {
514 cairo_pattern_set_extend( pPattern, CAIRO_EXTEND_PAD );
515 }
516
517 aScaledTextureMatrix.x0 = basegfx::fround( aScaledTextureMatrix.x0 );
518 aScaledTextureMatrix.y0 = basegfx::fround( aScaledTextureMatrix.y0 );
519
520 double x1, y1, x2, y2;
521 cairo_path_extents(pCairo, &x1, &y1, &x2, &y2);
522 aScaledTextureMatrix.x0 -= (x1 * aScaledTextureMatrix.xx);
523 aScaledTextureMatrix.y0 -= (y1 * aScaledTextureMatrix.yy);
524
525 cairo_pattern_set_matrix( pPattern, &aScaledTextureMatrix );
526
527 cairo_set_source( pCairo, pPattern );
528 if( !bHasAlpha )
529 cairo_set_operator( pCairo, CAIRO_OPERATOR_SOURCE );
530 cairo_fill( pCairo );
531
532 cairo_restore( pCairo );
533
534 cairo_pattern_destroy( pPattern );
535 }
536
537 if( data )
538 free( data );
539 }
540 else if( aTexture.Gradient.is() )
541 {
542 uno::Reference< lang::XServiceInfo > xRef( aTexture.Gradient, uno::UNO_QUERY );
543
544 SAL_INFO( "canvas.cairo", "gradient fill" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "gradient fill") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "gradient fill"), 0); } else { ::std::
ostringstream sal_detail_stream; sal_detail_stream << "gradient fill"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "544" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "gradient fill") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "544" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "gradient fill"), 0); } else { ::std::
ostringstream sal_detail_stream; sal_detail_stream << "gradient fill"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "544" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
545 if( xRef.is() && xRef->getImplementationName() == PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME"Canvas::ParametricPolyPolygon" )
546 {
547 // TODO(Q1): Maybe use dynamic_cast here
548
549 // TODO(E1): Return value
550 // TODO(F1): FillRule
551 SAL_INFO( "canvas.cairo", "known implementation" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "known implementation"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "551" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "known implementation"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"known implementation"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "551" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "known implementation") == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "551" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "known implementation"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"known implementation"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "551" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
552
553 ::canvas::ParametricPolyPolygon* pPolyImpl = static_cast< ::canvas::ParametricPolyPolygon* >( aTexture.Gradient.get() );
554 css::geometry::AffineMatrix2D aTransform( aTexture.AffineTransform );
555 cairo_matrix_t aTextureMatrix;
556
557 cairo_matrix_init( &aTextureMatrix,
558 aTransform.m00, aTransform.m10, aTransform.m01,
559 aTransform.m11, aTransform.m02, aTransform.m12);
560 if( pPolyImpl->getValues().meType == canvas::ParametricPolyPolygon::GradientType::Rectangular )
561 {
562 // no general path gradient yet in cairo; emulate then
563 cairo_save( pCairo );
564 cairo_clip( pCairo );
565
566 // fill bound rect with start color
567 cairo_rectangle( pCairo, rBounds.getMinX(), rBounds.getMinY(),
568 rBounds.getWidth(), rBounds.getHeight() );
569 setColor(pCairo,pPolyImpl->getValues().maColors[0]);
570 cairo_fill(pCairo);
571
572 cairo_transform( pCairo, &aTextureMatrix );
573
574 // longest line in gradient bound rect
575 const unsigned int nGradientSize(
576 static_cast<unsigned int>(
577 ::basegfx::B2DVector(rBounds.getMinimum() - rBounds.getMaximum()).getLength() + 1.0 ) );
578
579 // typical number for pixel of the same color (strip size)
580 const unsigned int nStripSize( nGradientSize < 50 ? 2 : 4 );
581
582 // use at least three steps, and at utmost the number of color
583 // steps
584 const unsigned int nStepCount(
585 std::max(
586 3U,
587 std::min(
588 nGradientSize / nStripSize,
589 128U )) + 1 );
590
591 const uno::Sequence<double>* pColors=&pPolyImpl->getValues().maColors[0];
592 basegfx::utils::KeyStopLerp aLerper(pPolyImpl->getValues().maStops);
593 for( unsigned int i=1; i<nStepCount; ++i )
594 {
595 const double fT( i/double(nStepCount) );
596
597 std::ptrdiff_t nIndex;
598 double fAlpha;
599 std::tie(nIndex,fAlpha)=aLerper.lerp(fT);
600
601 setColor(pCairo, lerp(pColors[nIndex], pColors[nIndex+1], fAlpha));
602 cairo_rectangle( pCairo, -1+fT, -1+fT, 2-2*fT, 2-2*fT );
603 cairo_fill(pCairo);
604 }
605
606 cairo_restore( pCairo );
607 }
608 else
609 {
610 cairo_pattern_t* pPattern = patternFromParametricPolyPolygon( *pPolyImpl );
611
612 if( pPattern )
613 {
614 SAL_INFO( "canvas.cairo", "filling with pattern" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "filling with pattern"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "614" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "filling with pattern"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"filling with pattern"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "614" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "filling with pattern") == 1) { ::sal_detail_log(
(::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "614" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "filling with pattern"), 0); } else { ::
std::ostringstream sal_detail_stream; sal_detail_stream <<
"filling with pattern"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "614" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
615
616 cairo_save( pCairo );
617
618 cairo_transform( pCairo, &aTextureMatrix );
619 cairo_set_source( pCairo, pPattern );
620 cairo_fill( pCairo );
621 cairo_restore( pCairo );
622
623 cairo_pattern_destroy( pPattern );
624 }
625 }
626 }
627 }
628 }
629 else
630 cairo_fill( pCairo );
631 SAL_INFO( "canvas.cairo", "fill")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "fill") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "631" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "fill"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "fill"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "631" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "fill") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "631" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "fill"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "fill"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "631" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
632 break;
633 case Stroke:
634 cairo_stroke( pCairo );
635 SAL_INFO( "canvas.cairo", "stroke")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "stroke") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "635" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "stroke"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "stroke"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "635" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "stroke") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "635" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "stroke"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "stroke"; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "635" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
636 break;
637 case Clip:
638 cairo_clip( pCairo );
639 SAL_INFO( "canvas.cairo", "clip")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "clip") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "639" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clip"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "clip"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "639" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "clip") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "639" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clip"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "clip"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "639" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
640 break;
641 }
642 }
643
644 static void clipNULL( cairo_t *pCairo )
645 {
646 SAL_INFO( "canvas.cairo", "clipNULL")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "clipNULL") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "646" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clipNULL"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "clipNULL"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "646" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "clipNULL") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "646" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "clipNULL"), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "clipNULL"; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "646" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
647 cairo_matrix_t aOrigMatrix, aIdentityMatrix;
648
649 /* we set identity matrix here to overcome bug in cairo 0.9.2
650 where XCreatePixmap is called with zero width and height.
651
652 it also reaches faster path in cairo clipping code.
653 */
654 cairo_matrix_init_identity( &aIdentityMatrix );
655 cairo_get_matrix( pCairo, &aOrigMatrix );
656 cairo_set_matrix( pCairo, &aIdentityMatrix );
657
658 cairo_reset_clip( pCairo );
659 cairo_rectangle( pCairo, 0, 0, 1, 1 );
660 cairo_clip( pCairo );
661 cairo_rectangle( pCairo, 2, 0, 1, 1 );
662 cairo_clip( pCairo );
663
664 /* restore the original matrix */
665 cairo_set_matrix( pCairo, &aOrigMatrix );
666 }
667
668 void doPolyPolygonImplementation( const ::basegfx::B2DPolyPolygon& aPolyPolygon,
669 Operation aOperation,
670 cairo_t* pCairo,
671 const uno::Sequence< rendering::Texture >* pTextures,
672 const SurfaceProviderRef& pDevice,
673 rendering::FillRule eFillrule )
674 {
675 if( pTextures )
676 ENSURE_ARG_OR_THROW( pTextures->hasElements(),if( !(pTextures->hasElements()) ) { do { if (true &&
(!(pTextures->hasElements()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "677" ": "), "%s", "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence"
), css::uno::Reference< css::uno::XInterface >(), 0 ); }
677 "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence")if( !(pTextures->hasElements()) ) { do { if (true &&
(!(pTextures->hasElements()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "677" ": "), "%s", "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "CanvasHelper::fillTexturedPolyPolygon: empty texture sequence"
), css::uno::Reference< css::uno::XInterface >(), 0 ); }
;
678
679 bool bOpToDo = false;
680 cairo_matrix_t aOrigMatrix, aIdentityMatrix;
681 double nX, nY, nBX, nBY, nAX, nAY, nLastX(0.0), nLastY(0.0);
682
683 cairo_get_matrix( pCairo, &aOrigMatrix );
684 cairo_matrix_init_identity( &aIdentityMatrix );
685 cairo_set_matrix( pCairo, &aIdentityMatrix );
686
687 cairo_set_fill_rule( pCairo,
688 eFillrule == rendering::FillRule_EVEN_ODD ?
689 CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING );
690
691 for( sal_uInt32 nPolygonIndex = 0; nPolygonIndex < aPolyPolygon.count(); nPolygonIndex++ )
692 {
693 const ::basegfx::B2DPolygon& aPolygon( aPolyPolygon.getB2DPolygon( nPolygonIndex ) );
694 const sal_uInt32 nPointCount( aPolygon.count() );
695 // to correctly render closed curves, need to output first
696 // point twice (so output one additional point)
697 const sal_uInt32 nExtendedPointCount( nPointCount +
698 int(aPolygon.isClosed() && aPolygon.areControlPointsUsed()) );
699
700 if( nPointCount > 1)
701 {
702 bool bIsBezier = aPolygon.areControlPointsUsed();
703 ::basegfx::B2DPoint aA, aB, aP;
704
705 for( sal_uInt32 j=0; j < nExtendedPointCount; j++ )
706 {
707 aP = aPolygon.getB2DPoint( j % nPointCount );
708
709 nX = aP.getX();
710 nY = aP.getY();
711 cairo_matrix_transform_point( &aOrigMatrix, &nX, &nY );
712
713 if (!bIsBezier && aOperation == Clip)
714 {
715 nX = basegfx::fround( nX );
716 nY = basegfx::fround( nY );
717 }
718
719 if( aOperation == Stroke )
720 {
721 nX += 0.5;
722 nY += 0.5;
723 }
724
725 if( j==0 )
726 {
727 cairo_move_to( pCairo, nX, nY );
728 SAL_INFO( "canvas.cairo", "move to " << nX << "," << nY )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "move to " << nX
<< "," << nY) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "728" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "move to " << nX << "," <<
nY), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "move to " << nX << "," << nY; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "728" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "move to " << nX << "," << nY) ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "728" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "move to " << nX << "," <<
nY), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "move to " << nX << "," << nY; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "728" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
729 }
730 else
731 {
732 if( bIsBezier )
733 {
734 aA = aPolygon.getNextControlPoint( (j-1) % nPointCount );
735 aB = aPolygon.getPrevControlPoint( j % nPointCount );
736
737 nAX = aA.getX();
738 nAY = aA.getY();
739 nBX = aB.getX();
740 nBY = aB.getY();
741
742 cairo_matrix_transform_point( &aOrigMatrix, &nAX, &nAY );
743 cairo_matrix_transform_point( &aOrigMatrix, &nBX, &nBY );
744
745 if( aOperation == Stroke )
746 {
747 nAX += 0.5;
748 nAY += 0.5;
749 nBX += 0.5;
750 nBY += 0.5;
751 }
752
753 // tdf#99165 if the control points are 'empty', create the mathematical
754 // correct replacement ones to avoid problems with the graphical sub-system
755 // tdf#101026 The 1st attempt to create a mathematically correct replacement control
756 // vector was wrong. Best alternative is one as close as possible which means short.
757 if (basegfx::fTools::equal(nAX, nLastX) && basegfx::fTools::equal(nAY, nLastY))
758 {
759 nAX = nLastX + ((nBX - nLastX) * 0.0005);
760 nAY = nLastY + ((nBY - nLastY) * 0.0005);
761 }
762
763 if(basegfx::fTools::equal(nBX, nX) && basegfx::fTools::equal(nBY, nY))
764 {
765 nBX = nX + ((nAX - nX) * 0.0005);
766 nBY = nY + ((nAY - nY) * 0.0005);
767 }
768
769 cairo_curve_to( pCairo, nAX, nAY, nBX, nBY, nX, nY );
770 }
771 else
772 {
773 cairo_line_to( pCairo, nX, nY );
774 SAL_INFO( "canvas.cairo", "line to " << nX << "," << nY )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "line to " << nX
<< "," << nY) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "774" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "line to " << nX << "," <<
nY), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "line to " << nX << "," << nY; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "774" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "line to " << nX << "," << nY) ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "774" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "line to " << nX << "," <<
nY), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "line to " << nX << "," << nY; ::
sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "774" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
775 }
776 bOpToDo = true;
777 }
778
779 nLastX = nX;
780 nLastY = nY;
781 }
782
783 if( aPolygon.isClosed() )
784 cairo_close_path( pCairo );
785
786 }
787 else
788 {
789 SAL_INFO( "canvas.cairo", "empty polygon for op: " << aOperation )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "empty polygon for op: "
<< aOperation) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "789" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "empty polygon for op: " << aOperation
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "empty polygon for op: " << aOperation; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "789" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "empty polygon for op: " << aOperation) == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "789" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "empty polygon for op: " << aOperation
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "empty polygon for op: " << aOperation; ::sal
::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "789" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
790 if( aOperation == Clip )
791 {
792 clipNULL( pCairo );
793
794 return;
795 }
796 }
797 }
798
799 if( aOperation == Fill && pTextures )
800 {
801 cairo_set_matrix( pCairo, &aOrigMatrix );
802 doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
803 cairo_set_matrix( pCairo, &aIdentityMatrix );
804 }
805
806 if( bOpToDo && ( aOperation != Fill || !pTextures ) )
807 doOperation( aOperation, pCairo, pTextures, pDevice, aPolyPolygon.getB2DRange() );
808
809 cairo_set_matrix( pCairo, &aOrigMatrix );
810
811 if( aPolyPolygon.count() == 0 && aOperation == Clip )
812 clipNULL( pCairo );
813 }
814
815 void CanvasHelper::doPolyPolygonPath( const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
816 Operation aOperation,
817 bool bNoLineJoin,
818 const uno::Sequence< rendering::Texture >* pTextures ) const
819 {
820 const ::basegfx::B2DPolyPolygon& rPolyPoly(
821 ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(xPolyPolygon) );
822
823 cairo_t* pCairo = mpCairo.get();
824
825 if(bNoLineJoin && aOperation == Stroke)
826 {
827 // emulate rendering::PathJoinType::NONE by painting single edges
828 for(sal_uInt32 a(0); a < rPolyPoly.count(); a++)
829 {
830 const basegfx::B2DPolygon& aCandidate(rPolyPoly.getB2DPolygon(a));
831 const sal_uInt32 nPointCount(aCandidate.count());
832
833 if(nPointCount)
834 {
835 const sal_uInt32 nEdgeCount(aCandidate.isClosed() ? nPointCount: nPointCount - 1);
836 basegfx::B2DPolygon aEdge;
837 aEdge.append(aCandidate.getB2DPoint(0));
838 aEdge.append(basegfx::B2DPoint(0.0, 0.0));
839
840 for(sal_uInt32 b(0); b < nEdgeCount; b++)
841 {
842 const sal_uInt32 nNextIndex((b + 1) % nPointCount);
843 aEdge.setB2DPoint(1, aCandidate.getB2DPoint(nNextIndex));
844 aEdge.setNextControlPoint(0, aCandidate.getNextControlPoint(b % nPointCount));
845 aEdge.setPrevControlPoint(1, aCandidate.getPrevControlPoint(nNextIndex));
846
847 doPolyPolygonImplementation( basegfx::B2DPolyPolygon(aEdge),
848 aOperation,
849 pCairo, pTextures,
850 mpSurfaceProvider,
851 xPolyPolygon->getFillRule() );
852
853 // prepare next step
854 aEdge.setB2DPoint(0, aEdge.getB2DPoint(1));
855 }
856 }
857 }
858 }
859 else
860 {
861 doPolyPolygonImplementation( rPolyPoly, aOperation,
862 pCairo, pTextures,
863 mpSurfaceProvider,
864 xPolyPolygon->getFillRule() );
865 }
866 }
867
868 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawPolyPolygon( const rendering::XCanvas* ,
869 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
870 const rendering::ViewState& viewState,
871 const rendering::RenderState& renderState )
872 {
873#ifdef CAIRO_CANVAS_PERF_TRACE
874 struct timespec aTimer;
875 mxDevice->startPerfTrace( &aTimer );
876#endif
877
878 if( mpCairo )
879 {
880 cairo_save( mpCairo.get() );
881
882 cairo_set_line_width( mpCairo.get(), 1 );
883
884 useStates( viewState, renderState, true );
885 doPolyPolygonPath( xPolyPolygon, Stroke );
886
887 cairo_restore( mpCairo.get() );
888 }
889 else
890 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper called after it was disposed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "890" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "890" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper called after it was disposed") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "890" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "890" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
891
892#ifdef CAIRO_CANVAS_PERF_TRACE
893 mxDevice->stopPerfTrace( &aTimer, "drawPolyPolygon" );
894#endif
895
896 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
897 }
898
899 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokePolyPolygon( const rendering::XCanvas* ,
900 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
901 const rendering::ViewState& viewState,
902 const rendering::RenderState& renderState,
903 const rendering::StrokeAttributes& strokeAttributes )
904 {
905#ifdef CAIRO_CANVAS_PERF_TRACE
906 struct timespec aTimer;
907 mxDevice->startPerfTrace( &aTimer );
908#endif
909
910 if( mpCairo )
911 {
912 cairo_save( mpCairo.get() );
913
914 useStates( viewState, renderState, true );
915
916 cairo_matrix_t aMatrix;
917 double w = strokeAttributes.StrokeWidth, h = 0;
918 cairo_get_matrix( mpCairo.get(), &aMatrix );
919 cairo_matrix_transform_distance( &aMatrix, &w, &h );
920 cairo_set_line_width( mpCairo.get(), w );
921
922 cairo_set_miter_limit( mpCairo.get(), strokeAttributes.MiterLimit );
923
924 // FIXME: cairo doesn't handle end cap so far (rodo)
925 switch( strokeAttributes.StartCapType )
926 {
927 case rendering::PathCapType::BUTT:
928 cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_BUTT );
929 break;
930 case rendering::PathCapType::ROUND:
931 cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_ROUND );
932 break;
933 case rendering::PathCapType::SQUARE:
934 cairo_set_line_cap( mpCairo.get(), CAIRO_LINE_CAP_SQUARE );
935 break;
936 }
937
938 bool bNoLineJoin(false);
939
940 switch( strokeAttributes.JoinType )
941 {
942 case rendering::PathJoinType::NONE:
943 bNoLineJoin = true;
944 [[fallthrough]]; // cairo doesn't have join type NONE so we use MITER as it's pretty close
945 case rendering::PathJoinType::MITER:
946 cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_MITER );
947 break;
948 case rendering::PathJoinType::ROUND:
949 cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_ROUND );
950 break;
951 case rendering::PathJoinType::BEVEL:
952 cairo_set_line_join( mpCairo.get(), CAIRO_LINE_JOIN_BEVEL );
953 break;
954 }
955
956 //tdf#103026 If the w scaling is 0, then all dashes become zero so
957 //cairo will set the cairo_t status to CAIRO_STATUS_INVALID_DASH
958 //and no further drawing will occur
959 if (strokeAttributes.DashArray.hasElements() && w > 0.0)
960 {
961 auto aDashArray(comphelper::sequenceToContainer<std::vector<double>>(strokeAttributes.DashArray));
962 for (auto& rDash : aDashArray)
963 rDash *= w;
964 cairo_set_dash(mpCairo.get(), aDashArray.data(), aDashArray.size(), 0);
965 }
966
967 // TODO(rodo) use LineArray of strokeAttributes
968
969 doPolyPolygonPath( xPolyPolygon, Stroke, bNoLineJoin );
970
971 cairo_restore( mpCairo.get() );
972 }
973 else
974 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper called after it was disposed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "974" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "974" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper called after it was disposed") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "974" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "974" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
975
976#ifdef CAIRO_CANVAS_PERF_TRACE
977 mxDevice->stopPerfTrace( &aTimer, "strokePolyPolygon" );
978#endif
979
980 // TODO(P1): Provide caching here.
981 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
982 }
983
984 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTexturedPolyPolygon( const rendering::XCanvas* ,
985 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
986 const rendering::ViewState& /*viewState*/,
987 const rendering::RenderState& /*renderState*/,
988 const uno::Sequence< rendering::Texture >& /*textures*/,
989 const rendering::StrokeAttributes& /*strokeAttributes*/ )
990 {
991 // TODO
992 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
993 }
994
995 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::strokeTextureMappedPolyPolygon( const rendering::XCanvas* ,
996 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
997 const rendering::ViewState& /*viewState*/,
998 const rendering::RenderState& /*renderState*/,
999 const uno::Sequence< rendering::Texture >& /*textures*/,
1000 const uno::Reference< geometry::XMapping2D >& /*xMapping*/,
1001 const rendering::StrokeAttributes& /*strokeAttributes*/ )
1002 {
1003 // TODO
1004 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
1005 }
1006
1007 uno::Reference< rendering::XPolyPolygon2D > CanvasHelper::queryStrokeShapes( const rendering::XCanvas* ,
1008 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
1009 const rendering::ViewState& /*viewState*/,
1010 const rendering::RenderState& /*renderState*/,
1011 const rendering::StrokeAttributes& /*strokeAttributes*/ )
1012 {
1013 // TODO
1014 return uno::Reference< rendering::XPolyPolygon2D >(nullptr);
1015 }
1016
1017 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillPolyPolygon( const rendering::XCanvas* ,
1018 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
1019 const rendering::ViewState& viewState,
1020 const rendering::RenderState& renderState )
1021 {
1022#ifdef CAIRO_CANVAS_PERF_TRACE
1023 struct timespec aTimer;
1024 mxDevice->startPerfTrace( &aTimer );
1025#endif
1026
1027 if( mpCairo )
1028 {
1029 cairo_save( mpCairo.get() );
1030
1031 useStates( viewState, renderState, true );
1032 doPolyPolygonPath( xPolyPolygon, Fill );
1033
1034 cairo_restore( mpCairo.get() );
1035 }
1036 else
1037 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper called after it was disposed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1037" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1037" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper called after it was disposed") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1037" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1037" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1038
1039#ifdef CAIRO_CANVAS_PERF_TRACE
1040 mxDevice->stopPerfTrace( &aTimer, "fillPolyPolygon" );
1041#endif
1042
1043 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
1044 }
1045
1046 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTexturedPolyPolygon( const rendering::XCanvas* ,
1047 const uno::Reference< rendering::XPolyPolygon2D >& xPolyPolygon,
1048 const rendering::ViewState& viewState,
1049 const rendering::RenderState& renderState,
1050 const uno::Sequence< rendering::Texture >& textures )
1051 {
1052 if( mpCairo )
1053 {
1054 cairo_save( mpCairo.get() );
1055
1056 useStates( viewState, renderState, true );
1057 doPolyPolygonPath( xPolyPolygon, Fill, false, &textures );
1058
1059 cairo_restore( mpCairo.get() );
1060 }
1061
1062 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
1063 }
1064
1065 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::fillTextureMappedPolyPolygon( const rendering::XCanvas* ,
1066 const uno::Reference< rendering::XPolyPolygon2D >& /*xPolyPolygon*/,
1067 const rendering::ViewState& /*viewState*/,
1068 const rendering::RenderState& /*renderState*/,
1069 const uno::Sequence< rendering::Texture >& /*textures*/,
1070 const uno::Reference< geometry::XMapping2D >& /*xMapping*/ )
1071 {
1072 // TODO
1073 return uno::Reference< rendering::XCachedPrimitive >(nullptr);
1074 }
1075
1076 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::implDrawBitmapSurface( const rendering::XCanvas* pCanvas,
1077 const SurfaceSharedPtr& pInputSurface,
1078 const rendering::ViewState& viewState,
1079 const rendering::RenderState& renderState,
1080 const geometry::IntegerSize2D& rSize,
1081 bool bModulateColors,
1082 bool bHasAlpha )
1083 {
1084 SurfaceSharedPtr pSurface=pInputSurface;
1085 uno::Reference< rendering::XCachedPrimitive > rv;
1086 geometry::IntegerSize2D aBitmapSize = rSize;
1087
1088 if( mpCairo )
1089 {
1090 cairo_save( mpCairo.get() );
1091
1092 cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
1093 cairo_clip( mpCairo.get() );
1094
1095 useStates( viewState, renderState, true );
1096
1097 cairo_matrix_t aMatrix;
1098
1099 cairo_get_matrix( mpCairo.get(), &aMatrix );
1100 if( ! ::rtl::math::approxEqual( aMatrix.xx, 1 ) &&
1101 ! ::rtl::math::approxEqual( aMatrix.yy, 1 ) &&
1102 ::rtl::math::approxEqual( aMatrix.x0, 0 ) &&
1103 ::rtl::math::approxEqual( aMatrix.y0, 0 ) &&
1104 basegfx::fround( rSize.Width * aMatrix.xx ) > 8 &&
1105 basegfx::fround( rSize.Height* aMatrix.yy ) > 8 )
1106 {
1107 double dWidth, dHeight;
1108
1109 dWidth = basegfx::fround( rSize.Width * aMatrix.xx );
1110 dHeight = basegfx::fround( rSize.Height* aMatrix.yy );
1111 aBitmapSize.Width = static_cast<sal_Int32>( dWidth );
1112 aBitmapSize.Height = static_cast<sal_Int32>( dHeight );
1113
1114 SurfaceSharedPtr pScaledSurface = mpSurfaceProvider->createSurface(
1115 ::basegfx::B2ISize( aBitmapSize.Width, aBitmapSize.Height ),
1116 bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR );
1117 CairoSharedPtr pCairo = pScaledSurface->getCairo();
1118
1119 cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE );
1120 // add 0.5px to size to avoid rounding errors in cairo, leading sometimes to random data on the image right/bottom borders
1121 cairo_scale( pCairo.get(), (dWidth+0.5)/rSize.Width, (dHeight+0.5)/rSize.Height );
1122 cairo_set_source_surface( pCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
1123 cairo_paint( pCairo.get() );
1124
1125 pSurface = pScaledSurface;
1126
1127 aMatrix.xx = aMatrix.yy = 1;
1128 cairo_set_matrix( mpCairo.get(), &aMatrix );
1129
1130 rv.set(
1131 new CachedBitmap( pSurface, viewState, renderState,
1132 // cast away const, need to
1133 // change refcount (as this is
1134 // ~invisible to client code,
1135 // still logically const)
1136 const_cast< rendering::XCanvas* >(pCanvas)) );
1137 }
1138
1139 if( !bHasAlpha && mbHaveAlpha )
1140 {
1141 double x, y, width, height;
1142
1143 x = y = 0;
1144 width = aBitmapSize.Width;
1145 height = aBitmapSize.Height;
1146 cairo_matrix_transform_point( &aMatrix, &x, &y );
1147 cairo_matrix_transform_distance( &aMatrix, &width, &height );
1148
1149 // in case the bitmap doesn't have alpha and covers whole area
1150 // we try to change surface to plain rgb
1151 SAL_INFO( "canvas.cairo","chance to change surface to rgb, " << x << ", " << y << ", " << width << " x " << height << " (" << maSize.getX() << " x " << maSize.getY() << ")" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "chance to change surface to rgb, "
<< x << ", " << y << ", " << width
<< " x " << height << " (" << maSize
.getX() << " x " << maSize.getY() << ")") ==
1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1151" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "chance to change surface to rgb, " <<
x << ", " << y << ", " << width <<
" x " << height << " (" << maSize.getX() <<
" x " << maSize.getY() << ")"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"chance to change surface to rgb, " << x << ", "
<< y << ", " << width << " x " <<
height << " (" << maSize.getX() << " x " <<
maSize.getY() << ")"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1151" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "chance to change surface to rgb, " << x <<
", " << y << ", " << width << " x " <<
height << " (" << maSize.getX() << " x " <<
maSize.getY() << ")") == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1151" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "chance to change surface to rgb, " <<
x << ", " << y << ", " << width <<
" x " << height << " (" << maSize.getX() <<
" x " << maSize.getY() << ")"), 0); } else { ::std
::ostringstream sal_detail_stream; sal_detail_stream <<
"chance to change surface to rgb, " << x << ", "
<< y << ", " << width << " x " <<
height << " (" << maSize.getX() << " x " <<
maSize.getY() << ")"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1151" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1152 if( x <= 0 && y <= 0 && x + width >= maSize.getX() && y + height >= maSize.getY() )
1153 {
1154 SAL_INFO( "canvas.cairo","trying to change surface to rgb")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "trying to change surface to rgb"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1154" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "trying to change surface to rgb"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "trying to change surface to rgb"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1154" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "trying to change surface to rgb") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1154" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "trying to change surface to rgb"), 0
); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "trying to change surface to rgb"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1154" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1155 if( mpSurfaceProvider ) {
1156 SurfaceSharedPtr pNewSurface = mpSurfaceProvider->changeSurface();
1157
1158 if( pNewSurface )
1159 setSurface( pNewSurface, false );
1160
1161 // set state to new mpCairo.get()
1162 useStates( viewState, renderState, true );
1163 // use the possibly modified matrix
1164 cairo_set_matrix( mpCairo.get(), &aMatrix );
1165 }
1166 }
1167 }
1168
1169 cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
1170 if( !bHasAlpha &&
1171 ::rtl::math::approxEqual( aMatrix.xx, 1 ) &&
1172 ::rtl::math::approxEqual( aMatrix.yy, 1 ) &&
1173 ::rtl::math::approxEqual( aMatrix.x0, 0 ) &&
1174 ::rtl::math::approxEqual( aMatrix.y0, 0 ) )
1175 cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE );
1176 cairo_pattern_set_extend( cairo_get_source(mpCairo.get()), CAIRO_EXTEND_PAD );
1177 cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height );
1178 cairo_clip( mpCairo.get() );
1179
1180 int nPixelWidth = std::round(rSize.Width * aMatrix.xx);
1181 int nPixelHeight = std::round(rSize.Height * aMatrix.yy);
1182 if (std::abs(nPixelWidth) > 0 && std::abs(nPixelHeight) > 0)
1183 {
1184 // Only render the image if it's at least 1x1 px sized.
1185 if (bModulateColors)
1186 cairo_paint_with_alpha(mpCairo.get(), renderState.DeviceColor[3]);
1187 else
1188 {
1189 cairo_paint(mpCairo.get());
1190 if (cairo_status(mpCairo.get()) != CAIRO_STATUS_SUCCESS)
1191 {
1192 SAL_WARN("canvas.cairo", "cairo_paint() failed: " << cairo_status_to_string(do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))) == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
1193 cairo_status(mpCairo.get())))do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
)) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), (
"canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))) == 1) { ::sal_detail_log( (::
SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "cairo_paint() failed: " << cairo_status_to_string
( cairo_status(mpCairo.get()))), 0); } else { ::std::ostringstream
sal_detail_stream; sal_detail_stream << "cairo_paint() failed: "
<< cairo_status_to_string( cairo_status(mpCairo.get())
); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1193" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1194 }
1195 }
1196 }
1197 cairo_restore( mpCairo.get() );
1198 }
1199 else
1200 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper called after it was disposed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1200" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1200" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper called after it was disposed") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1200" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1200" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1201
1202 return rv; // uno::Reference< rendering::XCachedPrimitive >(NULL);
1203 }
1204
1205 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmap( const rendering::XCanvas* pCanvas,
1206 const uno::Reference< rendering::XBitmap >& xBitmap,
1207 const rendering::ViewState& viewState,
1208 const rendering::RenderState& renderState )
1209 {
1210#ifdef CAIRO_CANVAS_PERF_TRACE
1211 struct timespec aTimer;
1212 mxDevice->startPerfTrace( &aTimer );
1213#endif
1214
1215 uno::Reference< rendering::XCachedPrimitive > rv;
1216 unsigned char* data = nullptr;
1217 bool bHasAlpha = false;
1218 SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
1219 geometry::IntegerSize2D aSize = xBitmap->getSize();
1220
1221 if( pSurface )
1222 {
1223 rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, false, bHasAlpha );
1224
1225 if( data )
1226 free( data );
1227 }
1228 else
1229 rv.set(nullptr);
1230
1231#ifdef CAIRO_CANVAS_PERF_TRACE
1232 mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
1233#endif
1234
1235 return rv;
1236 }
1237
1238 uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawBitmapModulated( const rendering::XCanvas* pCanvas,
1239 const uno::Reference< rendering::XBitmap >& xBitmap,
1240 const rendering::ViewState& viewState,
1241 const rendering::RenderState& renderState )
1242 {
1243#ifdef CAIRO_CANVAS_PERF_TRACE
1244 struct timespec aTimer;
1245 mxDevice->startPerfTrace( &aTimer );
1246#endif
1247
1248 uno::Reference< rendering::XCachedPrimitive > rv;
1249 unsigned char* data = nullptr;
1250 bool bHasAlpha = false;
1251 SurfaceSharedPtr pSurface = surfaceFromXBitmap( xBitmap, mpSurfaceProvider, data, bHasAlpha );
1252 geometry::IntegerSize2D aSize = xBitmap->getSize();
1253
1254 if( pSurface )
1255 {
1256 rv = implDrawBitmapSurface( pCanvas, pSurface, viewState, renderState, aSize, true, bHasAlpha );
1257
1258 if( data )
1259 free( data );
1260 }
1261 else
1262 rv.set(nullptr);
1263
1264#ifdef CAIRO_CANVAS_PERF_TRACE
1265 mxDevice->stopPerfTrace( &aTimer, "drawBitmap" );
1266#endif
1267
1268 return rv;
1269 }
1270
1271
1272 geometry::IntegerSize2D CanvasHelper::getSize() const
1273 {
1274 if( !mpSurfaceProvider )
1275 return geometry::IntegerSize2D(1, 1); // we're disposed
1276
1277 return ::basegfx::unotools::integerSize2DFromB2ISize( maSize );
1278 }
1279
1280 uno::Reference< rendering::XBitmap > CanvasHelper::getScaledBitmap( const geometry::RealSize2D& newSize,
1281 bool /*beFast*/ )
1282 {
1283#ifdef CAIRO_CANVAS_PERF_TRACE
1284 struct timespec aTimer;
1285 mxDevice->startPerfTrace( &aTimer );
1286#endif
1287
1288 if( mpCairo )
1289 {
1290 return uno::Reference< rendering::XBitmap >( new CanvasBitmap( ::basegfx::B2ISize( ::canvas::tools::roundUp( newSize.Width ),
1291 ::canvas::tools::roundUp( newSize.Height ) ),
1292 mpSurfaceProvider, mpDevice, false ) );
1293 }
1294 else
1295 SAL_INFO( "canvas.cairo", "CanvasHelper called after it was disposed")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper called after it was disposed"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1295" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1295" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper called after it was disposed") == 1
) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1295" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper called after it was disposed"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "CanvasHelper called after it was disposed"; ::sal::
detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"),
("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1295" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1296
1297#ifdef CAIRO_CANVAS_PERF_TRACE
1298 mxDevice->stopPerfTrace( &aTimer, "getScaledBitmap" );
1299#endif
1300
1301 return uno::Reference< rendering::XBitmap >();
1302 }
1303
1304 uno::Sequence< sal_Int8 > CanvasHelper::getData( rendering::IntegerBitmapLayout& aLayout,
1305 const geometry::IntegerRectangle2D& rect )
1306 {
1307 if( mpCairo )
1308 {
1309 const sal_Int32 nWidth( rect.X2 - rect.X1 );
1310 const sal_Int32 nHeight( rect.Y2 - rect.Y1 );
1311 const cairo_format_t eFormat( mbHaveAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24 );
1312 uno::Sequence< sal_Int8 > aRes( 4*nWidth*nHeight );
1313 sal_Int8* pData = aRes.getArray();
1314 cairo_surface_t* pImageSurface = cairo_image_surface_create_for_data( reinterpret_cast<unsigned char *>(pData),
1315 eFormat,
1316 nWidth, nHeight, 4*nWidth );
1317 cairo_t* pCairo = cairo_create( pImageSurface );
1318 cairo_set_source_surface( pCairo, mpSurface->getCairoSurface().get(), -rect.X1, -rect.Y1);
1319 cairo_paint( pCairo );
1320 cairo_destroy( pCairo );
1321 cairo_surface_destroy( pImageSurface );
1322
1323 aLayout = impl_getMemoryLayout( nWidth, nHeight );
1324
1325 return aRes;
1326 }
1327
1328 return uno::Sequence< sal_Int8 >();
1329 }
1330
1331 uno::Sequence< sal_Int8 > CanvasHelper::getPixel( rendering::IntegerBitmapLayout& /*bitmapLayout*/,
1332 const geometry::IntegerPoint2D& /*pos*/ )
1333 {
1334 return uno::Sequence< sal_Int8 >();
1335 }
1336
1337 namespace
1338 {
1339 class CairoColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace >
1340 {
1341 private:
1342 uno::Sequence< sal_Int8 > maComponentTags;
1343 uno::Sequence< sal_Int32 > maBitCounts;
1344
1345 virtual ::sal_Int8 SAL_CALL getType( ) override
1346 {
1347 return rendering::ColorSpaceType::RGB;
1348 }
1349 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) override
1350 {
1351 return maComponentTags;
1352 }
1353 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) override
1354 {
1355 return rendering::RenderingIntent::PERCEPTUAL;
1356 }
1357 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) override
1358 {
1359 return uno::Sequence< beans::PropertyValue >();
1360 }
1361 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
1362 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
1363 {
1364 // TODO(P3): if we know anything about target
1365 // colorspace, this can be greatly sped up
1366 uno::Sequence<rendering::ARGBColor> aIntermediate(
1367 convertToARGB(deviceColor));
1368 return targetColorSpace->convertFromARGB(aIntermediate);
1369 }
1370 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) override
1371 {
1372 const double* pIn( deviceColor.getConstArray() );
1373 const std::size_t nLen( deviceColor.getLength() );
1374 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1376" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1375 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1376" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1376 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1376" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1377
1378 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
1379 rendering::RGBColor* pOut( aRes.getArray() );
1380 for( std::size_t i=0; i<nLen; i+=4 )
1381 {
1382 const double fAlpha(pIn[3]);
1383 if( fAlpha == 0.0 )
1384 *pOut++ = rendering::RGBColor(0.0, 0.0, 0.0);
1385 else
1386 *pOut++ = rendering::RGBColor(pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha);
1387 pIn += 4;
1388 }
1389 return aRes;
1390 }
1391 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) override
1392 {
1393 const double* pIn( deviceColor.getConstArray() );
1394 const std::size_t nLen( deviceColor.getLength() );
1395 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1397" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1396 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1397" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1397 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1397" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1398
1399 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1400 rendering::ARGBColor* pOut( aRes.getArray() );
1401 for( std::size_t i=0; i<nLen; i+=4 )
1402 {
1403 const double fAlpha(pIn[3]);
1404 if( fAlpha == 0.0 )
1405 *pOut++ = rendering::ARGBColor(0.0, 0.0, 0.0, 0.0);
1406 else
1407 *pOut++ = rendering::ARGBColor(fAlpha,pIn[2]/fAlpha,pIn[1]/fAlpha,pIn[0]/fAlpha);
1408 pIn += 4;
1409 }
1410 return aRes;
1411 }
1412 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) override
1413 {
1414 const double* pIn( deviceColor.getConstArray() );
1415 const std::size_t nLen( deviceColor.getLength() );
1416 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1418" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1417 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1418" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1418 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1418" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1419
1420 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1421 rendering::ARGBColor* pOut( aRes.getArray() );
1422 for( std::size_t i=0; i<nLen; i+=4 )
1423 {
1424 *pOut++ = rendering::ARGBColor(pIn[3],pIn[2],pIn[1],pIn[1]);
1425 pIn += 4;
1426 }
1427 return aRes;
1428 }
1429 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
1430 {
1431 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1432 const std::size_t nLen( rgbColor.getLength() );
1433
1434 uno::Sequence< double > aRes(nLen*4);
1435 double* pColors=aRes.getArray();
1436 for( std::size_t i=0; i<nLen; ++i )
1437 {
1438 *pColors++ = pIn->Blue;
1439 *pColors++ = pIn->Green;
1440 *pColors++ = pIn->Red;
1441 *pColors++ = 1.0;
1442 ++pIn;
1443 }
1444 return aRes;
1445 }
1446 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1447 {
1448 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1449 const std::size_t nLen( rgbColor.getLength() );
1450
1451 uno::Sequence< double > aRes(nLen*4);
1452 double* pColors=aRes.getArray();
1453 for( std::size_t i=0; i<nLen; ++i )
1454 {
1455 *pColors++ = pIn->Alpha*pIn->Blue;
1456 *pColors++ = pIn->Alpha*pIn->Green;
1457 *pColors++ = pIn->Alpha*pIn->Red;
1458 *pColors++ = pIn->Alpha;
1459 ++pIn;
1460 }
1461 return aRes;
1462 }
1463 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1464 {
1465 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1466 const std::size_t nLen( rgbColor.getLength() );
1467
1468 uno::Sequence< double > aRes(nLen*4);
1469 double* pColors=aRes.getArray();
1470 for( std::size_t i=0; i<nLen; ++i )
1471 {
1472 *pColors++ = pIn->Blue;
1473 *pColors++ = pIn->Green;
1474 *pColors++ = pIn->Red;
1475 *pColors++ = pIn->Alpha;
1476 ++pIn;
1477 }
1478 return aRes;
1479 }
1480
1481 // XIntegerBitmapColorSpace
1482 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) override
1483 {
1484 return 32;
1485 }
1486 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) override
1487 {
1488 return maBitCounts;
1489 }
1490 virtual ::sal_Int8 SAL_CALL getEndianness( ) override
1491 {
1492 return util::Endianness::LITTLE;
1493 }
1494 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1495 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
1496 {
1497 if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) )
1498 {
1499 const sal_Int8* pIn( deviceColor.getConstArray() );
1500 const std::size_t nLen( deviceColor.getLength() );
1501 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1503" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1502 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1503" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1503 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1503" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1504
1505 uno::Sequence<double> aRes(nLen);
1506 double* pOut( aRes.getArray() );
1507 for( std::size_t i=0; i<nLen; i+=4 )
1508 {
1509 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1510 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1511 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1512 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1513 }
1514 return aRes;
1515 }
1516 else
1517 {
1518 // TODO(P3): if we know anything about target
1519 // colorspace, this can be greatly sped up
1520 uno::Sequence<rendering::ARGBColor> aIntermediate(
1521 convertIntegerToARGB(deviceColor));
1522 return targetColorSpace->convertFromARGB(aIntermediate);
1523 }
1524 }
1525 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1526 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) override
1527 {
1528 if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) )
1529 {
1530 // it's us, so simply pass-through the data
1531 return deviceColor;
1532 }
1533 else
1534 {
1535 // TODO(P3): if we know anything about target
1536 // colorspace, this can be greatly sped up
1537 uno::Sequence<rendering::ARGBColor> aIntermediate(
1538 convertIntegerToARGB(deviceColor));
1539 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1540 }
1541 }
1542 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1543 {
1544 const sal_Int8* pIn( deviceColor.getConstArray() );
1545 const std::size_t nLen( deviceColor.getLength() );
1546 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1548" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1547 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1548" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1548 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1548" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1549
1550 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
1551 rendering::RGBColor* pOut( aRes.getArray() );
1552 for( std::size_t i=0; i<nLen; i+=4 )
1553 {
1554 const double fAlpha(static_cast<sal_uInt8>(pIn[3]));
1555 if( fAlpha )
1556 *pOut++ = rendering::RGBColor(
1557 pIn[2]/fAlpha,
1558 pIn[1]/fAlpha,
1559 pIn[0]/fAlpha);
1560 else
1561 *pOut++ = rendering::RGBColor(0,0,0);
1562 pIn += 4;
1563 }
1564 return aRes;
1565 }
1566
1567 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1568 {
1569 const sal_Int8* pIn( deviceColor.getConstArray() );
1570 const std::size_t nLen( deviceColor.getLength() );
1571 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1573" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1572 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1573" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1573 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1573" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1574
1575 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1576 rendering::ARGBColor* pOut( aRes.getArray() );
1577 for( std::size_t i=0; i<nLen; i+=4 )
1578 {
1579 const double fAlpha(static_cast<sal_uInt8>(pIn[3]));
1580 if( fAlpha )
1581 *pOut++ = rendering::ARGBColor(
1582 fAlpha/255.0,
1583 pIn[2]/fAlpha,
1584 pIn[1]/fAlpha,
1585 pIn[0]/fAlpha);
1586 else
1587 *pOut++ = rendering::ARGBColor(0,0,0,0);
1588 pIn += 4;
1589 }
1590 return aRes;
1591 }
1592 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1593 {
1594 const sal_Int8* pIn( deviceColor.getConstArray() );
1595 const std::size_t nLen( deviceColor.getLength() );
1596 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1598" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1597 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1598" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1598 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1598" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1599
1600 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1601 rendering::ARGBColor* pOut( aRes.getArray() );
1602 for( std::size_t i=0; i<nLen; i+=4 )
1603 {
1604 *pOut++ = rendering::ARGBColor(
1605 vcl::unotools::toDoubleColor(pIn[3]),
1606 vcl::unotools::toDoubleColor(pIn[2]),
1607 vcl::unotools::toDoubleColor(pIn[1]),
1608 vcl::unotools::toDoubleColor(pIn[0]));
1609 pIn += 4;
1610 }
1611 return aRes;
1612 }
1613
1614 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
1615 {
1616 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1617 const std::size_t nLen( rgbColor.getLength() );
1618
1619 uno::Sequence< sal_Int8 > aRes(nLen*4);
1620 sal_Int8* pColors=aRes.getArray();
1621 for( std::size_t i=0; i<nLen; ++i )
1622 {
1623 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1624 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1625 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1626 *pColors++ = -1;
1627 ++pIn;
1628 }
1629 return aRes;
1630 }
1631
1632 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1633 {
1634 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1635 const std::size_t nLen( rgbColor.getLength() );
1636
1637 uno::Sequence< sal_Int8 > aRes(nLen*4);
1638 sal_Int8* pColors=aRes.getArray();
1639 for( std::size_t i=0; i<nLen; ++i )
1640 {
1641 const double fAlpha(pIn->Alpha);
1642 *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Blue);
1643 *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Green);
1644 *pColors++ = vcl::unotools::toByteColor(fAlpha*pIn->Red);
1645 *pColors++ = vcl::unotools::toByteColor(fAlpha);
1646 ++pIn;
1647 }
1648 return aRes;
1649 }
1650 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1651 {
1652 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1653 const std::size_t nLen( rgbColor.getLength() );
1654
1655 uno::Sequence< sal_Int8 > aRes(nLen*4);
1656 sal_Int8* pColors=aRes.getArray();
1657 for( std::size_t i=0; i<nLen; ++i )
1658 {
1659 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1660 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1661 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1662 *pColors++ = vcl::unotools::toByteColor(pIn->Alpha);
1663 ++pIn;
1664 }
1665 return aRes;
1666 }
1667
1668 public:
1669 CairoColorSpace() :
1670 maComponentTags(4),
1671 maBitCounts(4)
1672 {
1673 sal_Int8* pTags = maComponentTags.getArray();
1674 sal_Int32* pBitCounts = maBitCounts.getArray();
1675 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
1676 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
1677 pTags[2] = rendering::ColorComponentTag::RGB_RED;
1678 pTags[3] = rendering::ColorComponentTag::PREMULTIPLIED_ALPHA;
1679
1680 pBitCounts[0] =
1681 pBitCounts[1] =
1682 pBitCounts[2] =
1683 pBitCounts[3] = 8;
1684 }
1685 };
1686
1687 class CairoNoAlphaColorSpace : public cppu::WeakImplHelper< css::rendering::XIntegerBitmapColorSpace >
1688 {
1689 private:
1690 uno::Sequence< sal_Int8 > maComponentTags;
1691 uno::Sequence< sal_Int32 > maBitCounts;
1692
1693 virtual ::sal_Int8 SAL_CALL getType( ) override
1694 {
1695 return rendering::ColorSpaceType::RGB;
1696 }
1697 virtual uno::Sequence< ::sal_Int8 > SAL_CALL getComponentTags( ) override
1698 {
1699 return maComponentTags;
1700 }
1701 virtual ::sal_Int8 SAL_CALL getRenderingIntent( ) override
1702 {
1703 return rendering::RenderingIntent::PERCEPTUAL;
1704 }
1705 virtual uno::Sequence< beans::PropertyValue > SAL_CALL getProperties( ) override
1706 {
1707 return uno::Sequence< beans::PropertyValue >();
1708 }
1709 virtual uno::Sequence< double > SAL_CALL convertColorSpace( const uno::Sequence< double >& deviceColor,
1710 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
1711 {
1712 // TODO(P3): if we know anything about target
1713 // colorspace, this can be greatly sped up
1714 uno::Sequence<rendering::ARGBColor> aIntermediate(
1715 convertToARGB(deviceColor));
1716 return targetColorSpace->convertFromARGB(aIntermediate);
1717 }
1718 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertToRGB( const uno::Sequence< double >& deviceColor ) override
1719 {
1720 const double* pIn( deviceColor.getConstArray() );
1721 const std::size_t nLen( deviceColor.getLength() );
1722 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1724" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1723 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1724" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1724 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1724" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1725
1726 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
1727 rendering::RGBColor* pOut( aRes.getArray() );
1728 for( std::size_t i=0; i<nLen; i+=4 )
1729 {
1730 *pOut++ = rendering::RGBColor(pIn[2], pIn[1], pIn[0]);
1731 pIn += 4;
1732 }
1733 return aRes;
1734 }
1735 uno::Sequence< rendering::ARGBColor > impl_convertToARGB( const uno::Sequence< double >& deviceColor )
1736 {
1737 const double* pIn( deviceColor.getConstArray() );
1738 const std::size_t nLen( deviceColor.getLength() );
1739 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1741" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1740 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1741" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1741 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1741" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1742
1743 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1744 rendering::ARGBColor* pOut( aRes.getArray() );
1745 for( std::size_t i=0; i<nLen; i+=4 )
1746 {
1747 *pOut++ = rendering::ARGBColor(1.0, pIn[2], pIn[1], pIn[0]);
1748 pIn += 4;
1749 }
1750 return aRes;
1751 }
1752 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToARGB( const uno::Sequence< double >& deviceColor ) override
1753 {
1754 return impl_convertToARGB( deviceColor );
1755 }
1756 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertToPARGB( const uno::Sequence< double >& deviceColor ) override
1757 {
1758 return impl_convertToARGB( deviceColor );
1759 }
1760 virtual uno::Sequence< double > SAL_CALL convertFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
1761 {
1762 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1763 const std::size_t nLen( rgbColor.getLength() );
1764
1765 uno::Sequence< double > aRes(nLen*4);
1766 double* pColors=aRes.getArray();
1767 for( std::size_t i=0; i<nLen; ++i )
1768 {
1769 *pColors++ = pIn->Blue;
1770 *pColors++ = pIn->Green;
1771 *pColors++ = pIn->Red;
1772 *pColors++ = 1.0; // the value does not matter
1773 ++pIn;
1774 }
1775 return aRes;
1776 }
1777 uno::Sequence< double > impl_convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor )
1778 {
1779 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1780 const std::size_t nLen( rgbColor.getLength() );
1781
1782 uno::Sequence< double > aRes(nLen*4);
1783 double* pColors=aRes.getArray();
1784 for( std::size_t i=0; i<nLen; ++i )
1785 {
1786 *pColors++ = pIn->Blue;
1787 *pColors++ = pIn->Green;
1788 *pColors++ = pIn->Red;
1789 *pColors++ = 1.0; // the value does not matter
1790 ++pIn;
1791 }
1792 return aRes;
1793 }
1794 virtual uno::Sequence< double > SAL_CALL convertFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1795 {
1796 return impl_convertFromARGB( rgbColor );
1797 }
1798 virtual uno::Sequence< double > SAL_CALL convertFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1799 {
1800 return impl_convertFromARGB( rgbColor );
1801 }
1802
1803 // XIntegerBitmapColorSpace
1804 virtual ::sal_Int32 SAL_CALL getBitsPerPixel( ) override
1805 {
1806 return 32;
1807 }
1808 virtual uno::Sequence< ::sal_Int32 > SAL_CALL getComponentBitCounts( ) override
1809 {
1810 return maBitCounts;
1811 }
1812 virtual ::sal_Int8 SAL_CALL getEndianness( ) override
1813 {
1814 return util::Endianness::LITTLE;
1815 }
1816 virtual uno::Sequence<double> SAL_CALL convertFromIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1817 const uno::Reference< rendering::XColorSpace >& targetColorSpace ) override
1818 {
1819 if( dynamic_cast<CairoColorSpace*>(targetColorSpace.get()) )
1820 {
1821 const sal_Int8* pIn( deviceColor.getConstArray() );
1822 const std::size_t nLen( deviceColor.getLength() );
1823 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1825" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1824 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1825" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1825 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1825" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1826
1827 uno::Sequence<double> aRes(nLen);
1828 double* pOut( aRes.getArray() );
1829 for( std::size_t i=0; i<nLen; i+=4 )
1830 {
1831 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1832 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1833 *pOut++ = vcl::unotools::toDoubleColor(*pIn++);
1834 *pOut++ = 1.0; pIn++; // the value does not matter
1835 }
1836 return aRes;
1837 }
1838 else
1839 {
1840 // TODO(P3): if we know anything about target
1841 // colorspace, this can be greatly sped up
1842 uno::Sequence<rendering::ARGBColor> aIntermediate(
1843 convertIntegerToARGB(deviceColor));
1844 return targetColorSpace->convertFromARGB(aIntermediate);
1845 }
1846 }
1847 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertToIntegerColorSpace( const uno::Sequence< ::sal_Int8 >& deviceColor,
1848 const uno::Reference< rendering::XIntegerBitmapColorSpace >& targetColorSpace ) override
1849 {
1850 if( dynamic_cast<CairoNoAlphaColorSpace*>(targetColorSpace.get()) )
1851 {
1852 // it's us, so simply pass-through the data
1853 return deviceColor;
1854 }
1855 else
1856 {
1857 // TODO(P3): if we know anything about target
1858 // colorspace, this can be greatly sped up
1859 uno::Sequence<rendering::ARGBColor> aIntermediate(
1860 convertIntegerToARGB(deviceColor));
1861 return targetColorSpace->convertIntegerFromARGB(aIntermediate);
1862 }
1863 }
1864 virtual uno::Sequence< rendering::RGBColor > SAL_CALL convertIntegerToRGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1865 {
1866 const sal_Int8* pIn( deviceColor.getConstArray() );
1867 const std::size_t nLen( deviceColor.getLength() );
1868 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1870" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1869 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1870" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1870 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1870" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1871
1872 uno::Sequence< rendering::RGBColor > aRes(nLen/4);
1873 rendering::RGBColor* pOut( aRes.getArray() );
1874 for( std::size_t i=0; i<nLen; i+=4 )
1875 {
1876 *pOut++ = rendering::RGBColor( pIn[2], pIn[1], pIn[0] );
1877 pIn += 4;
1878 }
1879 return aRes;
1880 }
1881
1882 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1883 {
1884 return impl_convertIntegerToARGB( deviceColor );
1885 }
1886 virtual uno::Sequence< rendering::ARGBColor > SAL_CALL convertIntegerToPARGB( const uno::Sequence< ::sal_Int8 >& deviceColor ) override
1887 {
1888 return impl_convertIntegerToARGB( deviceColor );
1889 }
1890 uno::Sequence< rendering::ARGBColor > impl_convertIntegerToARGB( const uno::Sequence< ::sal_Int8 >& deviceColor )
1891 {
1892 const sal_Int8* pIn( deviceColor.getConstArray() );
1893 const std::size_t nLen( deviceColor.getLength() );
1894 ENSURE_ARG_OR_THROW2(nLen%4==0,if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1896" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1895 "number of channels no multiple of 4",if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1896" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
1896 static_cast<rendering::XColorSpace*>(this), 0)if( !(nLen%4==0) ) { do { if (true && (!(nLen%4==0)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "1896" ": "), "%s", "number of channels no multiple of 4"
); } } while (false); throw css::lang::IllegalArgumentException
( __func__ + OUStringLiteral(u",\n" "number of channels no multiple of 4"
), static_cast<rendering::XColorSpace*>(this), 0 ); }
;
1897
1898 uno::Sequence< rendering::ARGBColor > aRes(nLen/4);
1899 rendering::ARGBColor* pOut( aRes.getArray() );
1900 for( std::size_t i=0; i<nLen; i+=4 )
1901 {
1902 *pOut++ = rendering::ARGBColor(
1903 1.0,
1904 vcl::unotools::toDoubleColor(pIn[2]),
1905 vcl::unotools::toDoubleColor(pIn[1]),
1906 vcl::unotools::toDoubleColor(pIn[0]));
1907 pIn += 4;
1908 }
1909 return aRes;
1910 }
1911
1912 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromRGB( const uno::Sequence< rendering::RGBColor >& rgbColor ) override
1913 {
1914 const rendering::RGBColor* pIn( rgbColor.getConstArray() );
1915 const std::size_t nLen( rgbColor.getLength() );
1916
1917 uno::Sequence< sal_Int8 > aRes(nLen*4);
1918 sal_Int8* pColors=aRes.getArray();
1919 for( std::size_t i=0; i<nLen; ++i )
1920 {
1921 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1922 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1923 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1924 *pColors++ = -1; // the value does not matter
1925 ++pIn;
1926 }
1927 return aRes;
1928 }
1929
1930 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1931 {
1932 return impl_convertIntegerFromARGB( rgbColor );
1933 }
1934 virtual uno::Sequence< ::sal_Int8 > SAL_CALL convertIntegerFromPARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor ) override
1935 {
1936 return impl_convertIntegerFromARGB( rgbColor );
1937 }
1938 uno::Sequence< ::sal_Int8 > impl_convertIntegerFromARGB( const uno::Sequence< rendering::ARGBColor >& rgbColor )
1939 {
1940 const rendering::ARGBColor* pIn( rgbColor.getConstArray() );
1941 const std::size_t nLen( rgbColor.getLength() );
1942
1943 uno::Sequence< sal_Int8 > aRes(nLen*4);
1944 sal_Int8* pColors=aRes.getArray();
1945 for( std::size_t i=0; i<nLen; ++i )
1946 {
1947 *pColors++ = vcl::unotools::toByteColor(pIn->Blue);
1948 *pColors++ = vcl::unotools::toByteColor(pIn->Green);
1949 *pColors++ = vcl::unotools::toByteColor(pIn->Red);
1950 *pColors++ = -1; // the value does not matter
1951 ++pIn;
1952 }
1953 return aRes;
1954 }
1955
1956 public:
1957 CairoNoAlphaColorSpace() :
1958 maComponentTags(3),
1959 maBitCounts(3)
1960 {
1961 sal_Int8* pTags = maComponentTags.getArray();
1962 sal_Int32* pBitCounts = maBitCounts.getArray();
1963 pTags[0] = rendering::ColorComponentTag::RGB_BLUE;
1964 pTags[1] = rendering::ColorComponentTag::RGB_GREEN;
1965 pTags[2] = rendering::ColorComponentTag::RGB_RED;
1966
1967 pBitCounts[0] =
1968 pBitCounts[1] =
1969 pBitCounts[2] = 8;
1970 }
1971 };
1972
1973 struct CairoNoAlphaColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
1974 CairoNoAlphaColorSpaceHolder>
1975 {
1976 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
1977 {
1978 return new CairoNoAlphaColorSpace();
1979 }
1980 };
1981
1982 struct CairoColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>,
1983 CairoColorSpaceHolder>
1984 {
1985 uno::Reference<rendering::XIntegerBitmapColorSpace> operator()()
1986 {
1987 return new CairoColorSpace();
1988 }
1989 };
1990
1991 }
1992
1993 rendering::IntegerBitmapLayout CanvasHelper::getMemoryLayout()
1994 {
1995 if( !mpCairo )
1996 return rendering::IntegerBitmapLayout(); // we're disposed
1997
1998 const geometry::IntegerSize2D aSize(getSize());
1999
2000 return impl_getMemoryLayout( aSize.Width, aSize.Height );
2001 }
2002
2003 rendering::IntegerBitmapLayout
2004 CanvasHelper::impl_getMemoryLayout( const sal_Int32 nWidth, const sal_Int32 nHeight )
2005 {
2006 rendering::IntegerBitmapLayout aLayout;
2007
2008 aLayout.ScanLines = nHeight;
2009 aLayout.ScanLineBytes = nWidth*4;
2010 aLayout.ScanLineStride = aLayout.ScanLineBytes;
2011 aLayout.PlaneStride = 0;
2012 aLayout.ColorSpace = mbHaveAlpha ? CairoColorSpaceHolder::get() : CairoNoAlphaColorSpaceHolder::get();
2013 aLayout.Palette.clear();
2014 aLayout.IsMsbFirst = false;
2015
2016 return aLayout;
2017 }
2018
2019
2020 bool CanvasHelper::repaint( const SurfaceSharedPtr& pSurface,
2021 const rendering::ViewState& viewState,
2022 const rendering::RenderState& renderState )
2023 {
2024 SAL_INFO( "canvas.cairo", "CanvasHelper::repaint")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO
, "canvas.cairo")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "CanvasHelper::repaint"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"
), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "2024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper::repaint"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CanvasHelper::repaint"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "2024" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "CanvasHelper::repaint") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_INFO), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "2024" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "CanvasHelper::repaint"), 0); } else
{ ::std::ostringstream sal_detail_stream; sal_detail_stream <<
"CanvasHelper::repaint"; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO
), ("canvas.cairo"), ("/home/maarten/src/libreoffice/core/canvas/source/cairo/cairo_canvashelper.cxx"
":" "2024" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2025
2026 if( mpCairo )
2027 {
2028 cairo_save( mpCairo.get() );
2029
2030 cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() );
2031 cairo_clip( mpCairo.get() );
2032
2033 useStates( viewState, renderState, true );
2034
2035 cairo_matrix_t aMatrix;
2036
2037 cairo_get_matrix( mpCairo.get(), &aMatrix );
2038 aMatrix.xx = aMatrix.yy = 1;
2039 cairo_set_matrix( mpCairo.get(), &aMatrix );
2040
2041 cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 );
2042 cairo_paint( mpCairo.get() );
2043 cairo_restore( mpCairo.get() );
2044 }
2045
2046 return true;
2047 }
2048}
2049
2050/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

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

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

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

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

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

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
9
Assuming the condition is true
10
Taking true branch
40 delete this;
11
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif