summaryrefslogtreecommitdiff
path: root/canvas/source/cairo/cairo_canvashelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'canvas/source/cairo/cairo_canvashelper.cxx')
-rw-r--r--canvas/source/cairo/cairo_canvashelper.cxx131
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;
}