diff options
Diffstat (limited to 'canvas/source/cairo/cairo_canvashelper.cxx')
-rw-r--r-- | canvas/source/cairo/cairo_canvashelper.cxx | 131 |
1 files changed, 64 insertions, 67 deletions
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; } |