diff options
Diffstat (limited to 'canvas/source/cairo')
19 files changed, 273 insertions, 251 deletions
diff --git a/canvas/source/cairo/cairo_cachedbitmap.cxx b/canvas/source/cairo/cairo_cachedbitmap.cxx index c907367a49af..e548778b2fe4 100644 --- a/canvas/source/cairo/cairo_cachedbitmap.cxx +++ b/canvas/source/cairo/cairo_cachedbitmap.cxx @@ -21,7 +21,8 @@ #include <com/sun/star/rendering/XCanvas.hpp> #include <com/sun/star/rendering/RepaintResult.hpp> -#include <tools/diagnose_ex.h> +#include <utility> +#include <comphelper/diagnose_ex.hxx> #include "cairo_cachedbitmap.hxx" #include "cairo_repainttarget.hxx" @@ -32,21 +33,19 @@ using namespace ::com::sun::star; namespace cairocanvas { - CachedBitmap::CachedBitmap( const SurfaceSharedPtr& pSurface, + CachedBitmap::CachedBitmap( SurfaceSharedPtr pSurface, const rendering::ViewState& rUsedViewState, - const rendering::RenderState& rUsedRenderState, + rendering::RenderState aUsedRenderState, const uno::Reference< rendering::XCanvas >& rTarget ) : CachedPrimitiveBase( rUsedViewState, rTarget ), - mpSurface( pSurface ), - maRenderState( rUsedRenderState ) + mpSurface(std::move( pSurface )), + maRenderState(std::move( aUsedRenderState )) {} - void SAL_CALL CachedBitmap::disposing() + void CachedBitmap::disposing(std::unique_lock<std::mutex>& rGuard) { - ::osl::MutexGuard aGuard( m_aMutex ); - mpSurface.reset(); - CachedPrimitiveBase::disposing(); + CachedPrimitiveBase::disposing(rGuard); } ::sal_Int8 CachedBitmap::doRedraw( const rendering::ViewState& rNewState, diff --git a/canvas/source/cairo/cairo_cachedbitmap.hxx b/canvas/source/cairo/cairo_cachedbitmap.hxx index 0af07c07a6c8..d7f4c58ef681 100644 --- a/canvas/source/cairo/cairo_cachedbitmap.hxx +++ b/canvas/source/cairo/cairo_cachedbitmap.hxx @@ -34,13 +34,13 @@ namespace cairocanvas /** Create an XCachedPrimitive for given GraphicObject */ - CachedBitmap( const ::cairo::SurfaceSharedPtr& pSurface, - const css::rendering::ViewState& rUsedViewState, - const css::rendering::RenderState& rUsedRenderState, - const css::uno::Reference< css::rendering::XCanvas >& rTarget ); + CachedBitmap( ::cairo::SurfaceSharedPtr pSurface, + const css::rendering::ViewState& rUsedViewState, + css::rendering::RenderState aUsedRenderState, + const css::uno::Reference< css::rendering::XCanvas >& rTarget ); /// Dispose all internal references - virtual void SAL_CALL disposing() override; + virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; private: virtual ::sal_Int8 doRedraw( const css::rendering::ViewState& rNewState, diff --git a/canvas/source/cairo/cairo_canvas.cxx b/canvas/source/cairo/cairo_canvas.cxx index f8266cffe446..100ee51c0aa2 100644 --- a/canvas/source/cairo/cairo_canvas.cxx +++ b/canvas/source/cairo/cairo_canvas.cxx @@ -23,7 +23,7 @@ #include <com/sun/star/awt/Rectangle.hpp> #include <com/sun/star/lang/NoSupportException.hpp> #include <osl/mutex.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <vcl/sysdata.hxx> #include <vcl/skia/SkiaHelper.hxx> #include <cppuhelper/supportsservice.hxx> @@ -68,7 +68,6 @@ namespace cairocanvas sal_Int64 nPtr = 0; maArguments[0] >>= nPtr; OutputDevice* pOutDev = reinterpret_cast<OutputDevice*>(nPtr); - ENSURE_ARG_OR_THROW( pOutDev != nullptr, "Canvas::initialize: invalid OutDev pointer" ); @@ -111,7 +110,7 @@ namespace cairocanvas OUString SAL_CALL Canvas::getServiceName( ) { - return "com.sun.star.rendering.Canvas.Cairo"; + return u"com.sun.star.rendering.Canvas.Cairo"_ustr; } // XServiceInfo @@ -122,7 +121,7 @@ namespace cairocanvas } OUString Canvas::getImplementationName() { - return "com.sun.star.comp.rendering.Canvas.Cairo"; + return u"com.sun.star.comp.rendering.Canvas.Cairo"_ustr; } css::uno::Sequence< OUString > Canvas::getSupportedServiceNames() { @@ -176,16 +175,14 @@ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* com_sun_star_comp_rendering_Canvas_Cairo_get_implementation( css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args) { - auto p = new cairocanvas::Canvas(args, context); - p->acquire(); + rtl::Reference<cairocanvas::Canvas> p = new cairocanvas::Canvas(args, context); try { p->initialize(); } catch (css::uno::Exception&) { p->dispose(); - p->release(); throw; } - return static_cast<cppu::OWeakObject*>(p); + return cppu::acquire(p.get()); } diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx index 55f1603237b2..c4de75ee2fce 100644 --- a/canvas/source/cairo/cairo_canvasbitmap.cxx +++ b/canvas/source/cairo/cairo_canvasbitmap.cxx @@ -21,7 +21,8 @@ #include <sal/log.hxx> #include <cppuhelper/supportsservice.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> +#include <utility> #include <vcl/bitmapex.hxx> #include <vcl/BitmapTools.hxx> @@ -35,12 +36,10 @@ using namespace ::com::sun::star; namespace cairocanvas { CanvasBitmap::CanvasBitmap( const ::basegfx::B2ISize& rSize, - const SurfaceProviderRef& rSurfaceProvider, + SurfaceProviderRef rSurfaceProvider, rendering::XGraphicDevice* pDevice, bool bHasAlpha ) : - mpSurfaceProvider( rSurfaceProvider ), - mpBufferSurface(), - mpBufferCairo(), + mpSurfaceProvider(std::move( rSurfaceProvider )), maSize(rSize), mbHasAlpha(bHasAlpha) { @@ -49,7 +48,7 @@ namespace cairocanvas SAL_INFO( "canvas.cairo", - "bitmap size: " << rSize.getX() << "x" << rSize.getY()); + "bitmap size: " << rSize.getWidth() << "x" << rSize.getHeight()); mpBufferSurface = mpSurfaceProvider->createSurface( rSize, bHasAlpha ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR ); mpBufferCairo = mpBufferSurface->getCairo(); @@ -120,7 +119,7 @@ namespace cairocanvas break; BitmapEx* pBitmapEx = vcl::bitmap::CreateFromCairoSurface( - ::Size( maSize.getX(), maSize.getY() ), + ::Size( maSize.getWidth(), maSize.getHeight() ), getSurface()->getCairoSurface().get()); if (pBitmapEx) aRV <<= reinterpret_cast<sal_Int64>( pBitmapEx ); @@ -146,7 +145,7 @@ namespace cairocanvas OUString SAL_CALL CanvasBitmap::getImplementationName( ) { - return "CairoCanvas.CanvasBitmap"; + return u"CairoCanvas.CanvasBitmap"_ustr; } sal_Bool SAL_CALL CanvasBitmap::supportsService( const OUString& ServiceName ) @@ -156,7 +155,7 @@ namespace cairocanvas uno::Sequence< OUString > SAL_CALL CanvasBitmap::getSupportedServiceNames( ) { - return { "com.sun.star.rendering.CanvasBitmap" }; + return { u"com.sun.star.rendering.CanvasBitmap"_ustr }; } } diff --git a/canvas/source/cairo/cairo_canvasbitmap.hxx b/canvas/source/cairo/cairo_canvasbitmap.hxx index a4e55f7b642a..f2371821023f 100644 --- a/canvas/source/cairo/cairo_canvasbitmap.hxx +++ b/canvas/source/cairo/cairo_canvasbitmap.hxx @@ -69,7 +69,7 @@ namespace cairocanvas Reference device, with which bitmap should be compatible */ CanvasBitmap( const ::basegfx::B2ISize& rSize, - const SurfaceProviderRef& rDevice, + SurfaceProviderRef rDevice, css::rendering::XGraphicDevice* pDevice, bool bHasAlpha ); @@ -106,10 +106,9 @@ namespace cairocanvas // 0 ... get pointer to BitmapEx // 1 ... get X pixmap handle to rgb content // 2 ... FIXME: leftover? ever called with this? always returns nothing (empty Any) - // returned any contains either BitmapEx pointer or array of three Any value + // returned any contains either BitmapEx pointer or array of two Any value // 1st a bool value: true - free the pixmap after used by XFreePixmap, false do nothing, the pixmap is used internally in the canvas // 2nd the pixmap handle (sal_Int64) - // 3rd the pixmap depth virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override; virtual void SAL_CALL setFastPropertyValue(sal_Int32, const css::uno::Any&) override {} diff --git a/canvas/source/cairo/cairo_canvascustomsprite.cxx b/canvas/source/cairo/cairo_canvascustomsprite.cxx index b885071787d5..72fb291ebf35 100644 --- a/canvas/source/cairo/cairo_canvascustomsprite.cxx +++ b/canvas/source/cairo/cairo_canvascustomsprite.cxx @@ -22,7 +22,7 @@ #include <basegfx/point/b2dpoint.hxx> #include <cppuhelper/supportsservice.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <canvas/canvastools.hxx> #include <cairo.h> @@ -134,7 +134,7 @@ namespace cairocanvas OUString SAL_CALL CanvasCustomSprite::getImplementationName() { - return "CairoCanvas.CanvasCustomSprite"; + return u"CairoCanvas.CanvasCustomSprite"_ustr; } sal_Bool SAL_CALL CanvasCustomSprite::supportsService( const OUString& ServiceName ) @@ -144,7 +144,7 @@ namespace cairocanvas uno::Sequence< OUString > SAL_CALL CanvasCustomSprite::getSupportedServiceNames() { - return { "com.sun.star.rendering.CanvasCustomSprite" }; + return { u"com.sun.star.rendering.CanvasCustomSprite"_ustr }; } } diff --git a/canvas/source/cairo/cairo_canvasfont.cxx b/canvas/source/cairo/cairo_canvasfont.cxx index cca052d167e0..a2650811b721 100644 --- a/canvas/source/cairo/cairo_canvasfont.cxx +++ b/canvas/source/cairo/cairo_canvasfont.cxx @@ -24,8 +24,11 @@ #include <cppuhelper/supportsservice.hxx> #include <i18nlangtag/languagetag.hxx> #include <rtl/math.hxx> +#include <utility> #include <vcl/metric.hxx> +#include <canvas/canvastools.hxx> + #include "cairo_canvasfont.hxx" #include "cairo_textlayout.hxx" @@ -35,16 +38,18 @@ namespace cairocanvas { CanvasFont::CanvasFont( const rendering::FontRequest& rFontRequest, - const uno::Sequence< beans::PropertyValue >& /*rExtraFontProperties*/, + const uno::Sequence< beans::PropertyValue >& rExtraFontProperties, const geometry::Matrix2D& rFontMatrix, - const SurfaceProviderRef& rDevice ) : - CanvasFont_Base( m_aMutex ), + SurfaceProviderRef rDevice ) : maFont( vcl::Font( rFontRequest.FontDescription.FamilyName, rFontRequest.FontDescription.StyleName, Size( 0, ::basegfx::fround(rFontRequest.CellSize) ) ) ), maFontRequest( rFontRequest ), - mpRefDevice( rDevice ) + mpRefDevice(std::move( rDevice )), + mnEmphasisMark(0) { + ::canvas::tools::extractExtraFontProperties(rExtraFontProperties, mnEmphasisMark); + maFont->SetAlignment( ALIGN_BASELINE ); maFont->SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==css::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE ); maFont->SetVertical( rFontRequest.FontDescription.IsVertical==css::util::TriState_YES ); @@ -85,11 +90,14 @@ namespace cairocanvas pOutDev->EnableMapMode(bOldMapState); } - void SAL_CALL CanvasFont::disposing() + void CanvasFont::disposing(std::unique_lock<std::mutex>& rGuard) { - SolarMutexGuard aGuard; - - mpRefDevice.clear(); + rGuard.unlock(); + { + SolarMutexGuard aGuard; + mpRefDevice.clear(); + } + rGuard.lock(); } uno::Reference< rendering::XTextLayout > SAL_CALL CanvasFont::createTextLayout( const rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) @@ -108,8 +116,6 @@ namespace cairocanvas rendering::FontRequest SAL_CALL CanvasFont::getFontRequest( ) { - SolarMutexGuard aGuard; - return maFontRequest; } @@ -133,7 +139,7 @@ namespace cairocanvas OUString SAL_CALL CanvasFont::getImplementationName() { - return "CairoCanvas::CanvasFont"; + return u"CairoCanvas::CanvasFont"_ustr; } sal_Bool SAL_CALL CanvasFont::supportsService( const OUString& ServiceName ) @@ -143,7 +149,7 @@ namespace cairocanvas uno::Sequence< OUString > SAL_CALL CanvasFont::getSupportedServiceNames() { - return { "com.sun.star.rendering.CanvasFont" }; + return { u"com.sun.star.rendering.CanvasFont"_ustr }; } vcl::Font const & CanvasFont::getVCLFont() const diff --git a/canvas/source/cairo/cairo_canvasfont.hxx b/canvas/source/cairo/cairo_canvasfont.hxx index 0c26bee66b72..d5e015006c98 100644 --- a/canvas/source/cairo/cairo_canvasfont.hxx +++ b/canvas/source/cairo/cairo_canvasfont.hxx @@ -19,8 +19,7 @@ #pragma once -#include <cppuhelper/compbase.hxx> -#include <cppuhelper/basemutex.hxx> +#include <comphelper/compbase.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/geometry/Matrix2D.hpp> @@ -38,11 +37,10 @@ namespace cairocanvas { - typedef ::cppu::WeakComponentImplHelper< css::rendering::XCanvasFont, + typedef ::comphelper::WeakComponentImplHelper< css::rendering::XCanvasFont, css::lang::XServiceInfo > CanvasFont_Base; - class CanvasFont : public ::cppu::BaseMutex, - public CanvasFont_Base + class CanvasFont : public CanvasFont_Base { public: typedef rtl::Reference<CanvasFont> Reference; @@ -51,12 +49,12 @@ namespace cairocanvas const CanvasFont& operator=(const CanvasFont&) = delete; CanvasFont( const css::rendering::FontRequest& fontRequest, - const css::uno::Sequence< css::beans::PropertyValue >& extraFontProperties, + const css::uno::Sequence< css::beans::PropertyValue >& extraFontProperties, const css::geometry::Matrix2D& rFontMatrix, - const SurfaceProviderRef& rDevice ); + SurfaceProviderRef rDevice ); /// Dispose all internal references - virtual void SAL_CALL disposing() override; + virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; // XCanvasFont virtual css::uno::Reference< css::rendering::XTextLayout > SAL_CALL createTextLayout( const css::rendering::StringContext& aText, sal_Int8 nDirection, sal_Int64 nRandomSeed ) override; @@ -72,10 +70,13 @@ namespace cairocanvas vcl::Font const & getVCLFont() const; + sal_uInt32 getEmphasisMark() const { return mnEmphasisMark; } + private: ::canvas::vcltools::VCLObject<vcl::Font> maFont; css::rendering::FontRequest maFontRequest; SurfaceProviderRef mpRefDevice; + sal_uInt32 mnEmphasisMark; }; } diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx index 7d4cdba478f4..f09ce8c480bf 100644 --- a/canvas/source/cairo/cairo_canvashelper.cxx +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -41,9 +41,8 @@ #include <com/sun/star/util/Endianness.hpp> #include <comphelper/sequence.hxx> #include <cppuhelper/implbase.hxx> -#include <rtl/instance.hxx> #include <rtl/math.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <vcl/bitmapex.hxx> #include <vcl/BitmapTools.hxx> #include <vcl/canvastools.hxx> @@ -65,11 +64,7 @@ namespace cairocanvas CanvasHelper::CanvasHelper() : mpSurfaceProvider(nullptr), mpDevice(nullptr), - mpVirtualDevice(), - mbHaveAlpha(), - mpCairo(), - mpSurface(), - maSize() + mbHaveAlpha() { } @@ -214,7 +209,7 @@ namespace cairocanvas void CanvasHelper::clear() { - SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getX() << " x " << maSize.getY() ); + SAL_INFO( "canvas.cairo", "clear whole area: " << maSize.getWidth() << " x " << maSize.getHeight() ); if( !mpCairo ) return; @@ -231,7 +226,7 @@ namespace cairocanvas cairo_set_source_rgb( mpCairo.get(), 1.0, 1.0, 1.0 ); cairo_set_operator( mpCairo.get(), CAIRO_OPERATOR_SOURCE ); - cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); + cairo_rectangle( mpCairo.get(), 0, 0, maSize.getWidth(), maSize.getHeight() ); cairo_fill( mpCairo.get() ); cairo_restore( mpCairo.get() ); @@ -286,7 +281,7 @@ namespace cairocanvas cairo_restore( mpCairo.get() ); } -#define PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME "Canvas::ParametricPolyPolygon" +constexpr OUStringLiteral PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME = u"Canvas::ParametricPolyPolygon"; /** surfaceFromXBitmap Create a surface from XBitmap * @param xBitmap bitmap image that will be used for the surface @@ -316,7 +311,7 @@ namespace cairocanvas uno::Reference<rendering::XIntegerReadOnlyBitmap> xIntBmp(xBitmap, uno::UNO_QUERY_THROW); ::BitmapEx aBmpEx = vcl::unotools::bitmapExFromXBitmap(xIntBmp); - if( !!aBmpEx ) + if( !aBmpEx.IsEmpty() ) return aBmpEx; // TODO(F1): extract pixel from XBitmap interface @@ -351,7 +346,7 @@ namespace cairocanvas // there's no pixmap for alpha bitmap. we might still // use rgb pixmap and only access alpha pixels the // slow way. now we just speedup rgb bitmaps - if( !aBmpEx.IsTransparent() && !aBmpEx.IsAlpha() ) + if( !aBmpEx.IsAlpha() ) { pSurface = rSurfaceProvider->createSurface( aBitmap ); data = nullptr; @@ -364,14 +359,13 @@ namespace cairocanvas tools::Long nHeight; vcl::bitmap::CanvasCairoExtractBitmapData(aBmpEx, aBitmap, data, bHasAlpha, nWidth, nHeight); - SurfaceSharedPtr pImageSurface = rSurfaceProvider->getOutputDevice()->CreateSurface( + pSurface = rSurfaceProvider->getOutputDevice()->CreateSurface( CairoSurfaceSharedPtr( cairo_image_surface_create_for_data( data, bHasAlpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, nWidth, nHeight, nWidth*4 ), &cairo_surface_destroy) ); - pSurface = pImageSurface; SAL_INFO( "canvas.cairo","image: " << nWidth << " x " << nHeight << " alpha: " << bHasAlpha); } @@ -405,23 +399,25 @@ namespace cairocanvas { if( rLeft.getLength() == 3 ) { - uno::Sequence<double> aRes(3); - aRes[0] = basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha); - aRes[1] = basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha); - aRes[2] = basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha); - return aRes; + return + { + basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha), + basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha), + basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha) + }; } else if( rLeft.getLength() == 4 ) { - uno::Sequence<double> aRes(4); - aRes[0] = basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha); - aRes[1] = basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha); - aRes[2] = basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha); - aRes[3] = basegfx::utils::lerp(rLeft[3],rRight[3],fAlpha); - return aRes; + return + { + basegfx::utils::lerp(rLeft[0],rRight[0],fAlpha), + basegfx::utils::lerp(rLeft[1],rRight[1],fAlpha), + basegfx::utils::lerp(rLeft[2],rRight[2],fAlpha), + basegfx::utils::lerp(rLeft[3],rRight[3],fAlpha) + }; } - return uno::Sequence<double>(); + return {}; } static cairo_pattern_t* patternFromParametricPolyPolygon( ::canvas::ParametricPolyPolygon const & rPolygon ) @@ -492,7 +488,7 @@ namespace cairocanvas geometry::IntegerSize2D aSize = aTexture.Bitmap->getSize(); cairo_matrix_init_scale( &aScaleMatrix, 1.0/aSize.Width, 1.0/aSize.Height ); - cairo_matrix_multiply( &aScaledTextureMatrix, &aTextureMatrix, &aScaleMatrix ); + cairo_matrix_multiply( &aScaledTextureMatrix, &aScaleMatrix, &aTextureMatrix ); cairo_matrix_invert( &aScaledTextureMatrix ); // we don't care about repeat mode yet, so the workaround is disabled for now @@ -914,10 +910,12 @@ namespace cairocanvas useStates( viewState, renderState, true ); cairo_matrix_t aMatrix; - double w = strokeAttributes.StrokeWidth, h = 0; cairo_get_matrix( mpCairo.get(), &aMatrix ); - cairo_matrix_transform_distance( &aMatrix, &w, &h ); - cairo_set_line_width( mpCairo.get(), w ); + double scaleFactorX = 1; + double scaleFactorY = 0; + cairo_matrix_transform_distance( &aMatrix, &scaleFactorX, &scaleFactorY ); + double scaleFactor = basegfx::B2DVector( scaleFactorX, scaleFactorY ).getLength(); + cairo_set_line_width( mpCairo.get(), strokeAttributes.StrokeWidth * scaleFactor ); cairo_set_miter_limit( mpCairo.get(), strokeAttributes.MiterLimit ); @@ -953,14 +951,14 @@ namespace cairocanvas break; } - //tdf#103026 If the w scaling is 0, then all dashes become zero so + //tdf#103026 If the scaling is 0, then all dashes become zero so //cairo will set the cairo_t status to CAIRO_STATUS_INVALID_DASH //and no further drawing will occur - if (strokeAttributes.DashArray.hasElements() && w > 0.0) + if (strokeAttributes.DashArray.hasElements() && scaleFactor > 0.0) { auto aDashArray(comphelper::sequenceToContainer<std::vector<double>>(strokeAttributes.DashArray)); for (auto& rDash : aDashArray) - rDash *= w; + rDash *= scaleFactor; cairo_set_dash(mpCairo.get(), aDashArray.data(), aDashArray.size(), 0); } @@ -1089,7 +1087,7 @@ namespace cairocanvas { cairo_save( mpCairo.get() ); - cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); + cairo_rectangle( mpCairo.get(), 0, 0, maSize.getWidth(), maSize.getHeight() ); cairo_clip( mpCairo.get() ); useStates( viewState, renderState, true ); @@ -1148,8 +1146,8 @@ namespace cairocanvas // in case the bitmap doesn't have alpha and covers whole area // we try to change surface to plain rgb - SAL_INFO( "canvas.cairo","chance to change surface to rgb, " << x << ", " << y << ", " << width << " x " << height << " (" << maSize.getX() << " x " << maSize.getY() << ")" ); - if( x <= 0 && y <= 0 && x + width >= maSize.getX() && y + height >= maSize.getY() ) + SAL_INFO( "canvas.cairo","chance to change surface to rgb, " << x << ", " << y << ", " << width << " x " << height << " (" << maSize.getWidth() << " x " << maSize.getHeight() << ")" ); + if( x <= 0 && y <= 0 && x + width >= maSize.getWidth() && y + height >= maSize.getHeight() ) { SAL_INFO( "canvas.cairo","trying to change surface to rgb"); if( mpSurfaceProvider ) { @@ -1177,8 +1175,13 @@ namespace cairocanvas cairo_rectangle( mpCairo.get(), 0, 0, aBitmapSize.Width, aBitmapSize.Height ); cairo_clip( mpCairo.get() ); - int nPixelWidth = std::round(rSize.Width * aMatrix.xx); - int nPixelHeight = std::round(rSize.Height * aMatrix.yy); + // Use cairo_matrix_transform_distance() to determine the scaling, as that works even if + // the matrix also has rotation. + double fPixelWidth = rSize.Width; + double fPixelHeight = rSize.Height; + cairo_matrix_transform_distance(&aMatrix, &fPixelWidth, &fPixelHeight); + int nPixelWidth = std::round(fPixelWidth); + int nPixelHeight = std::round(fPixelHeight); if (std::abs(nPixelWidth) > 0 && std::abs(nPixelHeight) > 0) { // Only render the image if it's at least 1x1 px sized. @@ -1226,7 +1229,7 @@ namespace cairocanvas free( data ); } else - rv.set(nullptr); + rv.clear(); #ifdef CAIRO_CANVAS_PERF_TRACE mxDevice->stopPerfTrace( &aTimer, "drawBitmap" ); @@ -1259,7 +1262,7 @@ namespace cairocanvas free( data ); } else - rv.set(nullptr); + rv.clear(); #ifdef CAIRO_CANVAS_PERF_TRACE mxDevice->stopPerfTrace( &aTimer, "drawBitmap" ); @@ -1970,22 +1973,16 @@ namespace cairocanvas } }; - struct CairoNoAlphaColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, - CairoNoAlphaColorSpaceHolder> + uno::Reference<rendering::XIntegerBitmapColorSpace>& GetCairoNoAlphaColorSpace() { - uno::Reference<rendering::XIntegerBitmapColorSpace> operator()() - { - return new CairoNoAlphaColorSpace(); - } + static uno::Reference<rendering::XIntegerBitmapColorSpace> SPACE = new CairoNoAlphaColorSpace(); + return SPACE; }; - struct CairoColorSpaceHolder : public rtl::StaticWithInit<uno::Reference<rendering::XIntegerBitmapColorSpace>, - CairoColorSpaceHolder> + uno::Reference<rendering::XIntegerBitmapColorSpace>& GetCairoColorSpace() { - uno::Reference<rendering::XIntegerBitmapColorSpace> operator()() - { - return new CairoColorSpace(); - } + static uno::Reference<rendering::XIntegerBitmapColorSpace> SPACE = new CairoColorSpace(); + return SPACE; }; } @@ -2009,7 +2006,7 @@ namespace cairocanvas aLayout.ScanLineBytes = nWidth*4; aLayout.ScanLineStride = aLayout.ScanLineBytes; aLayout.PlaneStride = 0; - aLayout.ColorSpace = mbHaveAlpha ? CairoColorSpaceHolder::get() : CairoNoAlphaColorSpaceHolder::get(); + aLayout.ColorSpace = mbHaveAlpha ? GetCairoColorSpace() : GetCairoNoAlphaColorSpace(); aLayout.Palette.clear(); aLayout.IsMsbFirst = false; @@ -2023,25 +2020,25 @@ namespace cairocanvas { SAL_INFO( "canvas.cairo", "CanvasHelper::repaint"); - if( mpCairo ) - { - cairo_save( mpCairo.get() ); + if( !mpCairo ) + return true; - cairo_rectangle( mpCairo.get(), 0, 0, maSize.getX(), maSize.getY() ); - cairo_clip( mpCairo.get() ); + cairo_save( mpCairo.get() ); - useStates( viewState, renderState, true ); + cairo_rectangle( mpCairo.get(), 0, 0, maSize.getWidth(), maSize.getHeight() ); + cairo_clip( mpCairo.get() ); - cairo_matrix_t aMatrix; + useStates( viewState, renderState, true ); - cairo_get_matrix( mpCairo.get(), &aMatrix ); - aMatrix.xx = aMatrix.yy = 1; - cairo_set_matrix( mpCairo.get(), &aMatrix ); + cairo_matrix_t aMatrix; - cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 ); - cairo_paint( mpCairo.get() ); - cairo_restore( mpCairo.get() ); - } + cairo_get_matrix( mpCairo.get(), &aMatrix ); + aMatrix.xx = aMatrix.yy = 1; + cairo_set_matrix( mpCairo.get(), &aMatrix ); + + cairo_set_source_surface( mpCairo.get(), pSurface->getCairoSurface().get(), 0, 0 ); + cairo_paint( mpCairo.get() ); + cairo_restore( mpCairo.get() ); return true; } diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx index 2763800d5283..c8498bddf3b7 100644 --- a/canvas/source/cairo/cairo_canvashelper_text.cxx +++ b/canvas/source/cairo/cairo_canvashelper_text.cxx @@ -23,7 +23,7 @@ #include <rtl/math.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <vcl/canvastools.hxx> #include <vcl/metric.hxx> #include <vcl/virdev.hxx> @@ -99,7 +99,7 @@ namespace cairocanvas io_rVCLFont.SetFontHeight( ::basegfx::fround(nFontHeight * aScale.getY()) ); } - io_rVCLFont.SetOrientation( Degree10(static_cast< sal_Int16 >( ::basegfx::fround(-fmod(nRotate, 2*M_PI)*(1800.0/M_PI)) )) ); + io_rVCLFont.SetOrientation( Degree10( ::basegfx::fround(-basegfx::rad2deg<10>(fmod(nRotate, 2*M_PI))) ) ); // TODO(F2): Missing functionality in VCL: shearing o_rPoint.setX( ::basegfx::fround(aTranslate.getX()) ); @@ -190,6 +190,9 @@ namespace cairocanvas aVCLFont.SetColor( aColor ); aVCLFont.SetFillColor( aColor ); + if (pFont->getEmphasisMark()) + aVCLFont.SetEmphasisMark(FontEmphasisMark(pFont->getEmphasisMark())); + // no need to replicate this for mp2ndOutDev, we're modifying only aVCLFont here. if( !setupFontTransform( rOutDev, o_rOutPos, aVCLFont, viewState, renderState ) ) return false; @@ -226,21 +229,21 @@ namespace cairocanvas return uno::Reference< rendering::XCachedPrimitive >(nullptr); // no output necessary // change text direction and layout mode - ComplexTextLayoutFlags nLayoutMode(ComplexTextLayoutFlags::Default); + vcl::text::ComplexTextLayoutFlags nLayoutMode(vcl::text::ComplexTextLayoutFlags::Default); switch( textDirection ) { case rendering::TextDirection::WEAK_LEFT_TO_RIGHT: case rendering::TextDirection::STRONG_LEFT_TO_RIGHT: - nLayoutMode |= ComplexTextLayoutFlags::BiDiStrong; - nLayoutMode |= ComplexTextLayoutFlags::TextOriginLeft; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginLeft; break; case rendering::TextDirection::WEAK_RIGHT_TO_LEFT: - nLayoutMode |= ComplexTextLayoutFlags::BiDiRtl; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl; [[fallthrough]]; case rendering::TextDirection::STRONG_RIGHT_TO_LEFT: - nLayoutMode |= ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::BiDiStrong; - nLayoutMode |= ComplexTextLayoutFlags::TextOriginRight; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode |= vcl::text::ComplexTextLayoutFlags::TextOriginRight; break; } diff --git a/canvas/source/cairo/cairo_devicehelper.cxx b/canvas/source/cairo/cairo_devicehelper.cxx index e802e79cc2dd..3d3f7ef8301c 100644 --- a/canvas/source/cairo/cairo_devicehelper.cxx +++ b/canvas/source/cairo/cairo_devicehelper.cxx @@ -39,8 +39,7 @@ namespace cairocanvas { DeviceHelper::DeviceHelper() : mpSurfaceProvider( nullptr ), - mpRefDevice( nullptr ), - mpSurface() + mpRefDevice( nullptr ) { } @@ -77,7 +76,7 @@ namespace cairocanvas { SAL_INFO( "canvas.cairo", - "device size " << rSize.getX() << " x " << rSize.getY()); + "device size " << rSize.getWidth() << " x " << rSize.getHeight()); if( !mpRefDevice ) return; // disposed @@ -86,15 +85,15 @@ namespace cairocanvas // X11 only bool bReuseSurface = mpSurface && - mpSurface->Resize(rSize.getX() + pOutDev->GetOutOffXPixel(), - rSize.getY() + pOutDev->GetOutOffYPixel()); + mpSurface->Resize(rSize.getWidth() + pOutDev->GetOutOffXPixel(), + rSize.getHeight() + pOutDev->GetOutOffYPixel()); if (!bReuseSurface) { mpSurface = pOutDev->CreateSurface( pOutDev->GetOutOffXPixel(), pOutDev->GetOutOffYPixel(), - rSize.getX(), rSize.getY() ); + rSize.getWidth(), rSize.getHeight() ); } } @@ -210,22 +209,11 @@ namespace cairocanvas return uno::Any(); } - namespace - { - struct DeviceColorSpace: public rtl::StaticWithInit<uno::Reference<rendering::XColorSpace>, - DeviceColorSpace> - { - uno::Reference<rendering::XColorSpace> operator()() - { - return vcl::unotools::createStandardColorSpace(); - } - }; - } - uno::Reference<rendering::XColorSpace> const & DeviceHelper::getColorSpace() const { + static uno::Reference<rendering::XColorSpace> SPACE = vcl::unotools::createStandardColorSpace(); // always the same - return DeviceColorSpace::get(); + return SPACE; } void DeviceHelper::dumpScreenContent() const @@ -252,7 +240,7 @@ namespace cairocanvas SurfaceSharedPtr DeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) { if( mpSurface ) - return mpSurface->getSimilar( aContent, rSize.getX(), rSize.getY() ); + return mpSurface->getSimilar( aContent, rSize.getWidth(), rSize.getHeight() ); return SurfaceSharedPtr(); } diff --git a/canvas/source/cairo/cairo_repainttarget.hxx b/canvas/source/cairo/cairo_repainttarget.hxx index 558ec7921ecb..94d3d3845b3e 100644 --- a/canvas/source/cairo/cairo_repainttarget.hxx +++ b/canvas/source/cairo/cairo_repainttarget.hxx @@ -33,7 +33,7 @@ namespace cairocanvas This interface must be implemented on all canvas implementations that hand out XCachedPrimitives */ - class RepaintTarget + class SAL_LOPLUGIN_ANNOTATE("crosscast") RepaintTarget { public: virtual ~RepaintTarget() {} diff --git a/canvas/source/cairo/cairo_spritecanvas.cxx b/canvas/source/cairo/cairo_spritecanvas.cxx index ddb4491afdf2..be26b17774d7 100644 --- a/canvas/source/cairo/cairo_spritecanvas.cxx +++ b/canvas/source/cairo/cairo_spritecanvas.cxx @@ -27,7 +27,7 @@ #include <com/sun/star/lang/NoSupportException.hpp> #include <osl/mutex.hxx> #include <toolkit/helper/vclunohelper.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <cppuhelper/supportsservice.hxx> #include "cairo_spritecanvas.hxx" @@ -77,7 +77,7 @@ namespace cairocanvas throw lang::NoSupportException( "Parent window not VCL window, or canvas out-of-process!", nullptr); - bool bHasCairo = pParentWindow->SupportsCairo(); + bool bHasCairo = pParentWindow->GetOutDev()->SupportsCairo(); ENSURE_ARG_OR_THROW(bHasCairo, "CairoSpriteCanvas::SpriteCanvas: No Cairo capability"); @@ -144,7 +144,7 @@ namespace cairocanvas } OUString SpriteCanvas::getImplementationName() { - return "com.sun.star.comp.rendering.Canvas.Cairo"; + return u"com.sun.star.comp.rendering.SpriteCanvas.Cairo"_ustr; } css::uno::Sequence< OUString > SpriteCanvas::getSupportedServiceNames() { @@ -224,10 +224,9 @@ extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* com_sun_star_comp_rendering_SpriteCanvas_Cairo_get_implementation( css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args) { - auto p = new cairocanvas::SpriteCanvas(args, context); - p->acquire(); + rtl::Reference<cairocanvas::SpriteCanvas> p = new cairocanvas::SpriteCanvas(args, context); p->initialize(); - return static_cast<cppu::OWeakObject*>(p); + return cppu::acquire(p.get()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/source/cairo/cairo_spritecanvashelper.cxx b/canvas/source/cairo/cairo_spritecanvashelper.cxx index 47bde21e6f25..3fcfd734ab2f 100644 --- a/canvas/source/cairo/cairo_spritecanvashelper.cxx +++ b/canvas/source/cairo/cairo_spritecanvashelper.cxx @@ -23,7 +23,7 @@ #include <boost/cast.hpp> #include <basegfx/range/b2irange.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <canvas/canvastools.hxx> @@ -91,8 +91,6 @@ namespace cairocanvas SpriteCanvasHelper::SpriteCanvasHelper() : mpRedrawManager( nullptr ), mpOwningSpriteCanvas( nullptr ), - mpCompositingSurface(), - maCompositingSurfaceSize(), mbCompositingSurfaceDirty(true) { } @@ -187,7 +185,7 @@ namespace cairocanvas // background has changed, so we currently have no choice // but repaint everything (or caller requested that) - cairo_rectangle( pCompositingCairo.get(), 0, 0, rSize.getX(), rSize.getY() ); + cairo_rectangle( pCompositingCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() ); cairo_clip( pCompositingCairo.get() ); cairo_save( pCompositingCairo.get() ); cairo_set_source_surface( pCompositingCairo.get(), @@ -205,7 +203,7 @@ namespace cairocanvas ); // flush to screen - cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getX(), rSize.getY() ); + cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() ); cairo_clip( pWindowCairo.get() ); cairo_set_source_surface( pWindowCairo.get(), pCompositingSurface->getCairoSurface().get(), @@ -247,8 +245,8 @@ namespace cairocanvas const ::basegfx::B2ISize& rSize = mpOwningSpriteCanvas->getSizePixel(); const ::basegfx::B2IRange aOutputBounds( 0,0, - rSize.getX(), - rSize.getY() ); + rSize.getWidth(), + rSize.getHeight() ); SurfaceSharedPtr pCompositingSurface = getCompositingSurface(rSize); SurfaceSharedPtr pWindowSurface = mpOwningSpriteCanvas->getWindowSurface(); @@ -314,7 +312,7 @@ namespace cairocanvas aDestPos.getY() - aSourceUpperLeftPos.getY() ); cairo_rectangle( pScrollCairo.get(), aDestPos.getX(), aDestPos.getY(), - aScrollSize.getX(), aScrollSize.getY() ); + aScrollSize.getWidth(), aScrollSize.getHeight() ); cairo_clip( pScrollCairo.get() ); cairo_set_operator( pScrollCairo.get(), CAIRO_OPERATOR_SOURCE ); cairo_paint( pScrollCairo.get() ); @@ -327,7 +325,7 @@ namespace cairocanvas 0, 0 ); cairo_rectangle( pCompositingCairo.get(), aDestPos.getX(), aDestPos.getY(), - aScrollSize.getX(), aScrollSize.getY() ); + aScrollSize.getWidth(), aScrollSize.getHeight() ); cairo_clip( pCompositingCairo.get() ); cairo_set_operator( pCompositingCairo.get(), CAIRO_OPERATOR_SOURCE ); cairo_paint( pCompositingCairo.get() ); @@ -361,7 +359,7 @@ namespace cairocanvas repaintBackground( pCompositingCairo, mpOwningSpriteCanvas->getBufferSurface(), rArea ); - cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getX(), rSize.getY() ); + cairo_rectangle( pWindowCairo.get(), 0, 0, rSize.getWidth(), rSize.getHeight() ); cairo_clip( pWindowCairo.get() ); cairo_set_source_surface( pWindowCairo.get(), pCompositingSurface->getCairoSurface().get(), @@ -386,7 +384,7 @@ namespace cairocanvas CairoSharedPtr pCompositingCairo = pCompositingSurface->getCairo(); CairoSharedPtr pWindowCairo = pWindowSurface->getCairo(); - cairo_rectangle( pCompositingCairo.get(), 0, 0, rDeviceSize.getX(), rDeviceSize.getY() ); + cairo_rectangle( pCompositingCairo.get(), 0, 0, rDeviceSize.getWidth(), rDeviceSize.getHeight() ); cairo_clip( pCompositingCairo.get() ); ::basegfx::B2DVector aPos( ceil( rTotalArea.getMinX() ), ceil( rTotalArea.getMinY() ) ); @@ -404,7 +402,7 @@ namespace cairocanvas } // flush to screen - cairo_rectangle( pWindowCairo.get(), 0, 0, rDeviceSize.getX(), rDeviceSize.getY() ); + cairo_rectangle( pWindowCairo.get(), 0, 0, rDeviceSize.getWidth(), rDeviceSize.getHeight() ); cairo_clip( pWindowCairo.get() ); cairo_rectangle( pWindowCairo.get(), aPos.getX(), aPos.getY(), aSize.getX(), aSize.getY() ); cairo_clip( pWindowCairo.get() ); @@ -446,9 +444,9 @@ namespace cairocanvas // fraction of a sprite pixel... Limit size of VDev to output // device's area. const Size aOutputSize( - std::min( rSize.getX(), + std::min( rSize.getWidth(), ::canvas::tools::roundUp( rRequestedArea.getMaxX() - aOutputPosition.X()) ), - std::min( rSize.getY(), + std::min( rSize.getHeight(), ::canvas::tools::roundUp( rRequestedArea.getMaxY() - aOutputPosition.Y()) ) ); cairo_rectangle( pCompositingCairo.get(), aOutputPosition.X(), aOutputPosition.Y(), aOutputSize.Width(), aOutputSize.Height() ); @@ -484,8 +482,8 @@ namespace cairocanvas ::cairo::SurfaceSharedPtr const & SpriteCanvasHelper::getCompositingSurface( const ::basegfx::B2ISize& rNeededSize ) { - if( rNeededSize.getX() > maCompositingSurfaceSize.getX() || - rNeededSize.getY() > maCompositingSurfaceSize.getY() ) + if( rNeededSize.getWidth() > maCompositingSurfaceSize.getWidth() || + rNeededSize.getHeight() > maCompositingSurfaceSize.getHeight() ) { // need to give buffer more size mpCompositingSurface.reset(); @@ -513,7 +511,7 @@ namespace cairocanvas { return mpOwningSpriteCanvas->getWindowSurface()->getSimilar( CAIRO_CONTENT_COLOR, - rNeededSize.getX(), rNeededSize.getY() ); + rNeededSize.getWidth(), rNeededSize.getHeight() ); } } diff --git a/canvas/source/cairo/cairo_spritedevicehelper.cxx b/canvas/source/cairo/cairo_spritedevicehelper.cxx index 825d6f343b43..69a057c9918f 100644 --- a/canvas/source/cairo/cairo_spritedevicehelper.cxx +++ b/canvas/source/cairo/cairo_spritedevicehelper.cxx @@ -35,8 +35,6 @@ namespace cairocanvas SpriteDeviceHelper::SpriteDeviceHelper() : mpSpriteCanvas( nullptr ), - mpBufferSurface(), - maSize(), mbFullScreen( false ) {} @@ -46,7 +44,7 @@ namespace cairocanvas bool bFullscreen ) { DeviceHelper::init(rSpriteCanvas, - rOutputWindow); + *rOutputWindow.GetOutDev()); mpSpriteCanvas = &rSpriteCanvas; mbFullScreen = bFullscreen; @@ -92,7 +90,7 @@ namespace cairocanvas { SAL_INFO( "canvas.cairo", - "device size " << rSize.getX() << " x " << rSize.getY()); + "device size " << rSize.getWidth() << " x " << rSize.getHeight()); if( !mpSpriteCanvas ) return; // disposed @@ -104,7 +102,7 @@ namespace cairocanvas if( !mpBufferSurface ) mpBufferSurface = getWindowSurface()->getSimilar( CAIRO_CONTENT_COLOR, - rSize.getX(), rSize.getY() ); + rSize.getWidth(), rSize.getHeight() ); if( maSize != rSize ) maSize = rSize; @@ -126,7 +124,7 @@ namespace cairocanvas SurfaceSharedPtr SpriteDeviceHelper::createSurface( const ::basegfx::B2ISize& rSize, int aContent ) { if( mpBufferSurface ) - return mpBufferSurface->getSimilar( aContent, rSize.getX(), rSize.getY() ); + return mpBufferSurface->getSimilar( aContent, rSize.getWidth(), rSize.getHeight() ); return SurfaceSharedPtr(); } diff --git a/canvas/source/cairo/cairo_spritehelper.cxx b/canvas/source/cairo/cairo_spritehelper.cxx index 1fe9eb9152e0..4e536261989c 100644 --- a/canvas/source/cairo/cairo_spritehelper.cxx +++ b/canvas/source/cairo/cairo_spritehelper.cxx @@ -25,9 +25,10 @@ #include <basegfx/point/b2dpoint.hxx> #include <basegfx/utils/canvastools.hxx> #include <rtl/math.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <cairo.h> +#include <pixman.h> #include "cairo_spritehelper.hxx" @@ -37,8 +38,6 @@ using namespace ::com::sun::star; namespace cairocanvas { SpriteHelper::SpriteHelper() : - mpSpriteCanvas(), - mpBufferSurface(), mbTextureDirty(true) {} @@ -52,8 +51,7 @@ namespace cairocanvas mbTextureDirty = true; // also init base class - CanvasCustomSpriteHelper::init( rSpriteSize, - rSpriteCanvas.get() ); + CanvasCustomSpriteHelper::init( rSpriteSize, rSpriteCanvas ); } void SpriteHelper::setSurface( const SurfaceSharedPtr& pBufferSurface ) @@ -131,7 +129,7 @@ namespace cairocanvas rClip )); doPolyPolygonImplementation( aClipPoly, Clip, pCairo.get(), - nullptr, SurfaceProviderRef(mpSpriteCanvas.get()), + nullptr, SurfaceProviderRef(mpSpriteCanvas), rClip->getFillRule() ); } @@ -140,6 +138,37 @@ namespace cairocanvas cairo_clip( pCairo.get() ); cairo_set_matrix( pCairo.get(), &aOrigMatrix ); + cairo_matrix_t aInverseMatrix = aOrigMatrix; + bool matrixProblem = false; + // tdf#125949: Cairo internally uses the pixman library, and _cairo_matrix_to_pixman_matrix() + // checks all matrix components to fix PIXMAN_MAX_INT, which is about 32k. Which means that + // if our transformation is large, such as an initial step of some zooming animations, + // the conversion will fail. To make things worse, once something in cairo fails, it's treated + // as a fatal error, the error status of that cairo_t gets set, and there's no way to reset it + // besides recreating the whole cairo_t + // (https://lists.cairographics.org/archives/cairo/2006-September/007892.html). + // So copy&paste PIXMAN_MAX_INT here, and if our matrix could fail, bail out. +#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */ + if(cairo_matrix_invert(&aInverseMatrix) == CAIRO_STATUS_SUCCESS) + { + if(abs(aOrigMatrix.xx) > PIXMAN_MAX_INT || abs(aOrigMatrix.xx) > PIXMAN_MAX_INT + || abs(aOrigMatrix.xy) > PIXMAN_MAX_INT || abs(aOrigMatrix.yx) > PIXMAN_MAX_INT + || abs(aOrigMatrix.x0) > PIXMAN_MAX_INT || abs(aOrigMatrix.y0) > PIXMAN_MAX_INT + || abs(aInverseMatrix.xx) > PIXMAN_MAX_INT || abs(aInverseMatrix.xx) > PIXMAN_MAX_INT + || abs(aInverseMatrix.xy) > PIXMAN_MAX_INT || abs(aInverseMatrix.yx) > PIXMAN_MAX_INT + || abs(aInverseMatrix.x0) > PIXMAN_MAX_INT || abs(aInverseMatrix.y0) > PIXMAN_MAX_INT) + matrixProblem = true; +#undef PIXMAN_MAX_INT + } + else + matrixProblem = true; + if(matrixProblem) + { + SAL_WARN( "canvas.cairo", "matrix would overflow PIXMAN_MAX_INT, avoiding drawing" ); + cairo_restore( pCairo.get() ); + return; + } + if( isContentFullyOpaque() ) cairo_set_operator( pCairo.get(), CAIRO_OPERATOR_SOURCE ); cairo_set_source_surface( pCairo.get(), diff --git a/canvas/source/cairo/cairo_surfaceprovider.hxx b/canvas/source/cairo/cairo_surfaceprovider.hxx index a5115a507863..1ff6f2aa7d3f 100644 --- a/canvas/source/cairo/cairo_surfaceprovider.hxx +++ b/canvas/source/cairo/cairo_surfaceprovider.hxx @@ -37,7 +37,7 @@ namespace cairocanvas This interface must be implemented on all canvas implementations that hand out XCachedPrimitives */ - class SurfaceProvider : public css::uno::XInterface + class SAL_LOPLUGIN_ANNOTATE("crosscast") SurfaceProvider : public css::uno::XInterface { public: virtual ~SurfaceProvider() {} diff --git a/canvas/source/cairo/cairo_textlayout.cxx b/canvas/source/cairo/cairo_textlayout.cxx index 4094bd605e47..e033040d01b2 100644 --- a/canvas/source/cairo/cairo_textlayout.cxx +++ b/canvas/source/cairo/cairo_textlayout.cxx @@ -21,18 +21,18 @@ #include <sal/log.hxx> #include <math.h> -#include <memory> #include <com/sun/star/rendering/TextDirection.hpp> #include <canvas/canvastools.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/numeric/ftools.hxx> #include <cppuhelper/supportsservice.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> +#include <utility> +#include <vcl/kernarray.hxx> #include <vcl/metric.hxx> #include <vcl/virdev.hxx> - #include "cairo_textlayout.hxx" using namespace ::cairo; @@ -46,19 +46,19 @@ namespace cairocanvas sal_Int8 nTextDirection ) { // TODO(P3): avoid if already correctly set - ComplexTextLayoutFlags nLayoutMode = ComplexTextLayoutFlags::Default; + vcl::text::ComplexTextLayoutFlags nLayoutMode = vcl::text::ComplexTextLayoutFlags::Default; switch( nTextDirection ) { case rendering::TextDirection::WEAK_LEFT_TO_RIGHT: break; case rendering::TextDirection::STRONG_LEFT_TO_RIGHT: - nLayoutMode = ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiStrong; break; case rendering::TextDirection::WEAK_RIGHT_TO_LEFT: - nLayoutMode = ComplexTextLayoutFlags::BiDiRtl; + nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiRtl; break; case rendering::TextDirection::STRONG_RIGHT_TO_LEFT: - nLayoutMode = ComplexTextLayoutFlags::BiDiRtl | ComplexTextLayoutFlags::BiDiStrong; + nLayoutMode = vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::BiDiStrong; break; default: break; @@ -66,20 +66,18 @@ namespace cairocanvas // set calculated layout mode. Origin is always the left edge, // as required at the API spec - rOutDev.SetLayoutMode( nLayoutMode | ComplexTextLayoutFlags::TextOriginLeft ); + rOutDev.SetLayoutMode( nLayoutMode | vcl::text::ComplexTextLayoutFlags::TextOriginLeft ); } } - TextLayout::TextLayout( const rendering::StringContext& aText, - sal_Int8 nDirection, - sal_Int64 /*nRandomSeed*/, - const CanvasFont::Reference& rFont, - const SurfaceProviderRef& rRefDevice ) : - TextLayout_Base( m_aMutex ), - maText( aText ), - maLogicalAdvancements(), - mpFont( rFont ), - mpRefDevice( rRefDevice ), + TextLayout::TextLayout( rendering::StringContext aText, + sal_Int8 nDirection, + sal_Int64 /*nRandomSeed*/, + CanvasFont::Reference rFont, + SurfaceProviderRef rRefDevice ) : + maText(std::move( aText )), + mpFont(std::move( rFont )), + mpRefDevice(std::move( rRefDevice )), mnTextDirection( nDirection ) { } @@ -88,10 +86,8 @@ namespace cairocanvas { } - void SAL_CALL TextLayout::disposing() + void TextLayout::disposing(std::unique_lock<std::mutex>& /*rGuard*/) { - ::osl::MutexGuard aGuard( m_aMutex ); - mpFont.clear(); mpRefDevice.clear(); } @@ -117,27 +113,47 @@ namespace cairocanvas uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); return maLogicalAdvancements; } void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); if( aAdvancements.getLength() != maText.Length ) { SAL_WARN("canvas.cairo", "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" ); - throw lang::IllegalArgumentException("mismatching number of advancements", static_cast<cppu::OWeakObject*>(this), 1); + throw lang::IllegalArgumentException("mismatching number of advancements", getXWeak(), 1); } maLogicalAdvancements = aAdvancements; } + uno::Sequence< sal_Bool > SAL_CALL TextLayout::queryKashidaPositions( ) + { + std::unique_lock aGuard( m_aMutex ); + + return maKashidaPositions; + } + + void SAL_CALL TextLayout::applyKashidaPositions( const uno::Sequence< sal_Bool >& aPositions ) + { + std::unique_lock aGuard( m_aMutex ); + + if( aPositions.hasElements() && aPositions.getLength() != maText.Length ) + { + SAL_WARN("canvas.cairo", "TextLayout::applyKashidaPositions(): mismatching number of positions" ); + throw lang::IllegalArgumentException("mismatching number of positions", getXWeak(), 1); + } + + maKashidaPositions = aPositions; + } + geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); OutputDevice* pOutDev = mpRefDevice->getOutputDevice(); if( !pOutDev ) @@ -228,22 +244,18 @@ namespace cairocanvas sal_Int8 SAL_CALL TextLayout::getMainTextDirection( ) { - ::osl::MutexGuard aGuard( m_aMutex ); - return mnTextDirection; } uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( ) { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); - return mpFont.get(); + return mpFont; } rendering::StringContext SAL_CALL TextLayout::getText( ) { - ::osl::MutexGuard aGuard( m_aMutex ); - return maText; } @@ -261,17 +273,15 @@ namespace cairocanvas const rendering::ViewState& viewState, const rendering::RenderState& renderState ) const { - ::osl::MutexGuard aGuard( m_aMutex ); + std::unique_lock aGuard( m_aMutex ); setupLayoutMode( rOutDev, mnTextDirection ); - std::unique_ptr< tools::Long []> aOffsets(new tools::Long[maLogicalAdvancements.getLength()]); - - if( maLogicalAdvancements.hasElements() ) - setupTextOffsets( aOffsets.get(), maLogicalAdvancements, viewState, renderState ); - if (maLogicalAdvancements.hasElements()) { - rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets.get(), + KernArray aOffsets(setupTextOffsets(maLogicalAdvancements, viewState, renderState)); + std::span<const sal_Bool> aKashidaArray(maKashidaPositions.getConstArray(), maKashidaPositions.getLength()); + + rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets, aKashidaArray, ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition), ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) ); } @@ -288,8 +298,8 @@ namespace cairocanvas class OffsetTransformer { public: - explicit OffsetTransformer( const ::basegfx::B2DHomMatrix& rMat ) : - maMatrix( rMat ) + explicit OffsetTransformer( ::basegfx::B2DHomMatrix aMat ) : + maMatrix(std::move( aMat )) { } @@ -315,14 +325,11 @@ namespace cairocanvas }; } - void TextLayout::setupTextOffsets( tools::Long* outputOffsets, + KernArray TextLayout::setupTextOffsets( const uno::Sequence< double >& inputOffsets, const rendering::ViewState& viewState, const rendering::RenderState& renderState ) const { - ENSURE_OR_THROW( outputOffsets!=nullptr, - "TextLayout::setupTextOffsets offsets NULL" ); - ::basegfx::B2DHomMatrix aMatrix; ::canvas::tools::mergeViewAndRenderTransform(aMatrix, @@ -330,15 +337,16 @@ namespace cairocanvas renderState); // fill integer offsets - std::transform( inputOffsets.begin(), - inputOffsets.end(), - outputOffsets, - OffsetTransformer( aMatrix ) ); + KernArray outputOffsets; + OffsetTransformer aTransform(aMatrix); + std::for_each(inputOffsets.begin(), inputOffsets.end(), + [&outputOffsets, &aTransform](double n) {outputOffsets.push_back(aTransform(n)); } ); + return outputOffsets; } OUString SAL_CALL TextLayout::getImplementationName() { - return "CairoCanvas::TextLayout"; + return u"CairoCanvas::TextLayout"_ustr; } sal_Bool SAL_CALL TextLayout::supportsService( const OUString& ServiceName ) @@ -348,7 +356,7 @@ namespace cairocanvas uno::Sequence< OUString > SAL_CALL TextLayout::getSupportedServiceNames() { - return { "com.sun.star.rendering.TextLayout" }; + return { u"com.sun.star.rendering.TextLayout"_ustr }; } } diff --git a/canvas/source/cairo/cairo_textlayout.hxx b/canvas/source/cairo/cairo_textlayout.hxx index b4159e737e48..ed8265e8b391 100644 --- a/canvas/source/cairo/cairo_textlayout.hxx +++ b/canvas/source/cairo/cairo_textlayout.hxx @@ -19,8 +19,7 @@ #pragma once -#include <cppuhelper/compbase.hxx> -#include <cppuhelper/basemutex.hxx> +#include <comphelper/compbase.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/rendering/RenderState.hpp> @@ -36,25 +35,24 @@ namespace cairocanvas { - typedef ::cppu::WeakComponentImplHelper< css::rendering::XTextLayout, + typedef ::comphelper::WeakComponentImplHelper< css::rendering::XTextLayout, css::lang::XServiceInfo > TextLayout_Base; - class TextLayout : public ::cppu::BaseMutex, - public TextLayout_Base + class TextLayout : public TextLayout_Base { public: /// make noncopyable TextLayout(const TextLayout&) = delete; const TextLayout& operator=(const TextLayout&) = delete; - TextLayout( const css::rendering::StringContext& aText, - sal_Int8 nDirection, - sal_Int64 nRandomSeed, - const CanvasFont::Reference& rFont, - const SurfaceProviderRef& rRefDevice ); + TextLayout( css::rendering::StringContext aText, + sal_Int8 nDirection, + sal_Int64 nRandomSeed, + CanvasFont::Reference rFont, + SurfaceProviderRef rRefDevice ); /// Dispose all internal references - virtual void SAL_CALL disposing() override; + virtual void disposing(std::unique_lock<std::mutex>& rGuard) override; // XTextLayout virtual css::uno::Sequence< css::uno::Reference< css::rendering::XPolyPolygon2D > > SAL_CALL queryTextShapes( ) override; @@ -62,6 +60,8 @@ namespace cairocanvas virtual css::uno::Sequence< css::geometry::RealRectangle2D > SAL_CALL queryMeasures( ) override; virtual css::uno::Sequence< double > SAL_CALL queryLogicalAdvancements( ) override; virtual void SAL_CALL applyLogicalAdvancements( const css::uno::Sequence< double >& aAdvancements ) override; + virtual css::uno::Sequence< sal_Bool > SAL_CALL queryKashidaPositions( ) override; + virtual void SAL_CALL applyKashidaPositions( const css::uno::Sequence< sal_Bool >& aPositions ) override; virtual css::geometry::RealRectangle2D SAL_CALL queryTextBounds( ) override; virtual double SAL_CALL justify( double nSize ) override; virtual double SAL_CALL combinedJustify( const css::uno::Sequence< css::uno::Reference< css::rendering::XTextLayout > >& aNextLayouts, double nSize ) override; @@ -85,7 +85,7 @@ namespace cairocanvas const css::rendering::ViewState& viewState, const css::rendering::RenderState& renderState ) const; - void setupTextOffsets( tools::Long* outputOffsets, + KernArray setupTextOffsets( const css::uno::Sequence< double >& inputOffsets, const css::rendering::ViewState& viewState, const css::rendering::RenderState& renderState ) const; @@ -96,6 +96,7 @@ namespace cairocanvas private: css::rendering::StringContext maText; css::uno::Sequence< double > maLogicalAdvancements; + css::uno::Sequence< sal_Bool > maKashidaPositions; CanvasFont::Reference mpFont; SurfaceProviderRef mpRefDevice; sal_Int8 mnTextDirection; |