converting the SalGraphics backend from BitmapEx->Bitmap (3)
pass a single SalBitmap in drawTransformedBitmap Change-Id: Iacb67804e47867f4ab85b394b14f052807925b75 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190498 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
This commit is contained in:
@@ -547,7 +547,7 @@ void impBufferDevice::paint(double fTrans)
|
||||
aSizePixel.Width(), aSizePixel.Height(),
|
||||
maDestPixel.TopLeft().X(),
|
||||
maDestPixel.TopLeft().Y()),
|
||||
BitmapEx(aContent), 1 - fTrans);
|
||||
aContent, 1 - fTrans);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -183,6 +183,48 @@ public:
|
||||
sal_Int32 nX,
|
||||
sal_Int32 nY) const;
|
||||
|
||||
/** Create transformed Bitmap
|
||||
|
||||
@param fWidth
|
||||
The target width in pixels
|
||||
|
||||
@param fHeight
|
||||
The target height in pixels
|
||||
|
||||
@param rTransformation
|
||||
The back transformation for each pixel in (0 .. fWidth),(0 .. fHeight) to
|
||||
local pixel coordinates
|
||||
*/
|
||||
[[nodiscard]]
|
||||
Bitmap TransformBitmap(
|
||||
double fWidth,
|
||||
double fHeight,
|
||||
const basegfx::B2DHomMatrix& rTransformation) const;
|
||||
|
||||
/** Create transformed Bitmap
|
||||
|
||||
@param rTransformation
|
||||
The transformation from unit coordinates to the unit range
|
||||
|
||||
@param rVisibleRange
|
||||
The relative visible range in unit coordinates, relative to (0,0,1,1) which
|
||||
defines the whole target area
|
||||
|
||||
@param fMaximumArea
|
||||
A limitation for the maximum size of pixels to use for the result
|
||||
|
||||
The target size of the result bitmap is defined by transforming the given
|
||||
rTargetRange with the given rTransformation; the area of the result is
|
||||
linearly scaled to not exceed the given fMaximumArea
|
||||
|
||||
@return The transformed bitmap
|
||||
*/
|
||||
[[nodiscard]]
|
||||
SAL_DLLPRIVATE Bitmap getTransformed(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const basegfx::B2DRange& rVisibleRange,
|
||||
double fMaximumArea) const;
|
||||
|
||||
/** Convert bitmap format
|
||||
|
||||
@param eConversion
|
||||
|
||||
@@ -1388,10 +1388,6 @@ public:
|
||||
@param fAlpha
|
||||
Optional additional alpha to use for drawing (0 to 1, 1 being no change).
|
||||
*/
|
||||
void DrawTransformedBitmapEx(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const BitmapEx& rBitmapEx,
|
||||
double fAlpha = 1.0);
|
||||
void DrawTransformedBitmapEx(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const Bitmap& rBitmap,
|
||||
@@ -1415,13 +1411,13 @@ protected:
|
||||
/** Transform and draw a bitmap directly
|
||||
|
||||
@param aFullTransform The B2DHomMatrix used for the transformation
|
||||
@param rBitmapEx Reference to the bitmap to be transformed and drawn
|
||||
@param rBitmap Reference to the bitmap to be transformed and drawn
|
||||
|
||||
@return true if it was able to draw the bitmap, false if not
|
||||
*/
|
||||
virtual bool DrawTransformBitmapExDirect(
|
||||
const basegfx::B2DHomMatrix& aFullTransform,
|
||||
const BitmapEx& rBitmapEx,
|
||||
const Bitmap& rBitmap,
|
||||
double fAlpha = 1.0);
|
||||
|
||||
/** Transform and reduce the area that needs to be drawn of the bitmap and return the new
|
||||
|
||||
@@ -164,7 +164,7 @@ protected:
|
||||
const Point& rSrcPtPixel, const Size& rSrcSizePixel) override;
|
||||
|
||||
bool DrawTransformBitmapExDirect( const basegfx::B2DHomMatrix& aFullTransform,
|
||||
const BitmapEx& rBitmapEx, double fAlpha = 1.0) override;
|
||||
const Bitmap& rBitmap, double fAlpha = 1.0) override;
|
||||
|
||||
bool TransformAndReduceBitmapExToTargetRange( const basegfx::B2DHomMatrix& aFullTransform,
|
||||
basegfx::B2DRange &aVisibleRange, double &fMaximumArea) override;
|
||||
|
||||
@@ -37,7 +37,7 @@ Bitmap OutputDeviceTestBitmap::setupDrawTransformedBitmap(vcl::PixelFormat aBitm
|
||||
aTransform.translate((maVDRectangle.GetWidth() / 2.0) - (aBitmapSize.Width() / 2.0),
|
||||
(maVDRectangle.GetHeight() / 2.0) - (aBitmapSize.Height() / 2.0));
|
||||
|
||||
mpVirtualDevice->DrawTransformedBitmapEx(aTransform, BitmapEx(aBitmap));
|
||||
mpVirtualDevice->DrawTransformedBitmapEx(aTransform, aBitmap);
|
||||
|
||||
return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
|
||||
}
|
||||
@@ -59,7 +59,7 @@ Bitmap OutputDeviceTestBitmap::setupComplexDrawTransformedBitmap(vcl::PixelForma
|
||||
aTransform.scale(aBitmapSize.Width() * 2, aBitmapSize.Height() * 2);
|
||||
aTransform.translate(1, 1);
|
||||
|
||||
mpVirtualDevice->DrawTransformedBitmapEx(aTransform, BitmapEx(aBitmap));
|
||||
mpVirtualDevice->DrawTransformedBitmapEx(aTransform, aBitmap);
|
||||
|
||||
return mpVirtualDevice->GetBitmap(maVDRectangle.TopLeft(), maVDRectangle.GetSize());
|
||||
}
|
||||
|
||||
@@ -1699,16 +1699,8 @@ void CairoCommon::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rS
|
||||
|
||||
bool CairoCommon::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha,
|
||||
bool bAntiAlias)
|
||||
double fAlpha, bool bAntiAlias)
|
||||
{
|
||||
if (pAlphaBitmap && pAlphaBitmap->GetBitCount() != 8 && pAlphaBitmap->GetBitCount() != 1)
|
||||
{
|
||||
SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawTransformedBitmap alpha depth case: "
|
||||
<< pAlphaBitmap->GetBitCount());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fAlpha != 1.0)
|
||||
return false;
|
||||
|
||||
@@ -1725,26 +1717,6 @@ bool CairoCommon::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const ba
|
||||
return false;
|
||||
}
|
||||
|
||||
// MM02 try to access buffered MaskHelper
|
||||
std::shared_ptr<MaskHelper> aMask;
|
||||
if (nullptr != pAlphaBitmap)
|
||||
{
|
||||
tryToUseMaskBuffer(*pAlphaBitmap, aMask);
|
||||
}
|
||||
|
||||
// access cairo_surface_t from MaskHelper
|
||||
cairo_surface_t* mask(nullptr);
|
||||
if (aMask)
|
||||
{
|
||||
mask = aMask->getSurface(nDestWidth, nDestHeight);
|
||||
}
|
||||
|
||||
if (nullptr != pAlphaBitmap && nullptr == mask)
|
||||
{
|
||||
SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawTransformedBitmap case");
|
||||
return false;
|
||||
}
|
||||
|
||||
const Size aSize = rSourceBitmap.GetSize();
|
||||
cairo_t* cr = getCairoContext(false, bAntiAlias);
|
||||
clipRegion(cr);
|
||||
@@ -1765,10 +1737,7 @@ bool CairoCommon::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const ba
|
||||
cairo_clip(cr);
|
||||
|
||||
cairo_set_source_surface(cr, source, 0, 0);
|
||||
if (mask)
|
||||
cairo_mask_surface(cr, mask, 0, 0);
|
||||
else
|
||||
cairo_paint(cr);
|
||||
cairo_paint(cr);
|
||||
|
||||
releaseCairoContext(cr, false, extents);
|
||||
|
||||
|
||||
@@ -214,10 +214,9 @@ void SvpGraphicsBackend::drawAlphaBitmap(const SalTwoRect& rTR, const SalBitmap&
|
||||
bool SvpGraphicsBackend::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha)
|
||||
const SalBitmap& rSourceBitmap, double fAlpha)
|
||||
{
|
||||
return m_rCairoCommon.drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha,
|
||||
return m_rCairoCommon.drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, fAlpha,
|
||||
getAntiAlias());
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ struct VCL_DLLPUBLIC CairoCommon
|
||||
|
||||
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha, bool bAntiAlias);
|
||||
double fAlpha, bool bAntiAlias);
|
||||
|
||||
void drawMask(const SalTwoRect& rTR, const SalBitmap& rSalBitmap, Color nMaskColor,
|
||||
bool bAntiAlias);
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
|
||||
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override;
|
||||
double fAlpha) override;
|
||||
|
||||
bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
|
||||
sal_uInt8 nTransparency) override;
|
||||
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
|
||||
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override;
|
||||
double fAlpha) override;
|
||||
|
||||
bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
|
||||
sal_uInt8 nTransparency) override;
|
||||
|
||||
@@ -344,7 +344,7 @@ public:
|
||||
|
||||
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override;
|
||||
double fAlpha) override;
|
||||
|
||||
bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
|
||||
sal_uInt8 nTransparency) override;
|
||||
|
||||
+2
-4
@@ -363,7 +363,6 @@ public:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha,
|
||||
const OutputDevice& rOutDev );
|
||||
|
||||
@@ -521,7 +520,6 @@ protected:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha) = 0;
|
||||
|
||||
/// Returns true if the drawTransformedBitmap() call is fast, and so it should
|
||||
@@ -793,9 +791,9 @@ public:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override
|
||||
double fAlpha) override
|
||||
{
|
||||
return GetImpl()->drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha);
|
||||
return GetImpl()->drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, fAlpha);
|
||||
}
|
||||
|
||||
bool hasFastDrawTransformedBitmap() const override
|
||||
|
||||
@@ -185,7 +185,6 @@ public:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha) = 0;
|
||||
|
||||
/// Only currently true for SkiaSalGraphicsImpl
|
||||
|
||||
@@ -150,7 +150,7 @@ public:
|
||||
/** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
|
||||
virtual bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override;
|
||||
double fAlpha) override;
|
||||
|
||||
virtual bool hasFastDrawTransformedBitmap() const override;
|
||||
|
||||
@@ -251,12 +251,10 @@ protected:
|
||||
void setCanvasScalingAndClipping();
|
||||
void resetCanvasScalingAndClipping();
|
||||
static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region);
|
||||
sk_sp<SkImage> mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap,
|
||||
const Size& targetSize);
|
||||
sk_sp<SkImage> mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const Size& targetSize);
|
||||
using DirectImage = SkiaHelper::DirectImage;
|
||||
static OString makeCachedImageKey(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap,
|
||||
const Size& targetSize, DirectImage bitmapType,
|
||||
DirectImage alphaBitmapType);
|
||||
static OString makeCachedImageKey(const SkiaSalBitmap& bitmap, const Size& targetSize,
|
||||
DirectImage bitmapType);
|
||||
|
||||
// Skia uses floating point coordinates, so when we use integer coordinates, sometimes
|
||||
// rounding results in off-by-one errors (down), especially when drawing using GPU,
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
void* ImplGethDIB() const { return mpDIB; }
|
||||
HBITMAP ImplGethDDB() const { return mhDDB; }
|
||||
|
||||
std::shared_ptr< Gdiplus::Bitmap > ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource = nullptr) const;
|
||||
std::shared_ptr< Gdiplus::Bitmap > ImplGetGdiPlusBitmap() const;
|
||||
|
||||
static void ImplCreateDIB( const Size& rSize, vcl::PixelFormat ePixelFormat, const BitmapPalette& rPal,
|
||||
void*& rpDIB, sal_Int32 &rnDIBSize );
|
||||
|
||||
@@ -126,7 +126,6 @@ public:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha) override;
|
||||
|
||||
virtual bool hasFastDrawTransformedBitmap() const override;
|
||||
|
||||
@@ -653,12 +653,11 @@ public:
|
||||
for (int j = 0; j < 8; ++j)
|
||||
pWriteAccess->SetPixel(j, i, COL_BLACK);
|
||||
}
|
||||
BitmapEx aBitmapEx(aBitmap);
|
||||
basegfx::B2DHomMatrix aMatrix;
|
||||
// Draw with no transformation, only alpha change.
|
||||
aMatrix.scale(16, 16);
|
||||
device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
|
||||
BitmapEx result(device->GetBitmap(Point(0, 0), Size(16, 16)));
|
||||
device->DrawTransformedBitmapEx(aMatrix, aBitmap, 0.5);
|
||||
Bitmap result(device->GetBitmap(Point(0, 0), Size(16, 16)));
|
||||
CPPUNIT_ASSERT_EQUAL(COL_GRAY, result.GetPixelColor(0, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(15, 15));
|
||||
// Draw rotated and move to the bottom-left corner.
|
||||
@@ -667,7 +666,7 @@ public:
|
||||
aMatrix.scale(16, 16);
|
||||
aMatrix.rotate(M_PI / 2);
|
||||
aMatrix.translate(8, 8);
|
||||
device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
|
||||
device->DrawTransformedBitmapEx(aMatrix, aBitmap, 0.5);
|
||||
result = device->GetBitmap(Point(0, 0), Size(16, 16));
|
||||
CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(0, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(COL_GRAY, result.GetPixelColor(0, 15));
|
||||
@@ -1401,7 +1400,7 @@ public:
|
||||
bitmap.GetSizePixel().Height()); // draw as 10x10
|
||||
// Draw a blue bitmap to the device. The bug was that there was no alpha, but OutputDevice::DrawTransformBitmapExDirect()
|
||||
// supplied a fully opaque alpha done with Erase() on the alpha bitmap, and Skia backend didn't handle such alpha correctly.
|
||||
device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap));
|
||||
device->DrawTransformedBitmapEx(matrix, bitmap);
|
||||
exportDevice(u"tdf136171.png"_ustr, device);
|
||||
// The whole virtual device content now should be blue.
|
||||
CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(0, 0)));
|
||||
|
||||
@@ -356,7 +356,6 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapEx)
|
||||
}
|
||||
}
|
||||
}
|
||||
BitmapEx aBitmapEx(aBitmap);
|
||||
basegfx::B2DHomMatrix aMatrix;
|
||||
aMatrix.scale(8, 8);
|
||||
// Rotate 90 degrees clockwise, so the black part goes to the top right.
|
||||
@@ -365,7 +364,7 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapEx)
|
||||
aMtf.Record(pVDev.get());
|
||||
|
||||
// Draw the rotated bitmap on the vdev.
|
||||
pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
|
||||
pVDev->DrawTransformedBitmapEx(aMatrix, aBitmap);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
|
||||
MetaAction* pAction = aMtf.GetAction(0);
|
||||
CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
|
||||
@@ -420,7 +419,6 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapExFlip)
|
||||
}
|
||||
}
|
||||
}
|
||||
BitmapEx aBitmapEx(aBitmap);
|
||||
basegfx::B2DHomMatrix aMatrix;
|
||||
// Negative y scale: bitmap should be upside down, so the black part goes to the bottom left.
|
||||
aMatrix.scale(8, -8);
|
||||
@@ -430,7 +428,7 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawTransformedBitmapExFlip)
|
||||
aMtf.Record(pVDev.get());
|
||||
|
||||
// Draw the scaled and rotated bitmap on the vdev.
|
||||
pVDev->DrawTransformedBitmapEx(aMatrix, aBitmapEx);
|
||||
pVDev->DrawTransformedBitmapEx(aMatrix, aBitmap);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf.GetActionSize());
|
||||
MetaAction* pAction = aMtf.GetAction(0);
|
||||
CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE, pAction->GetType());
|
||||
|
||||
@@ -149,7 +149,7 @@ void SkiaTest::testDrawShaders()
|
||||
basegfx::B2DHomMatrix matrix;
|
||||
matrix.scale(10, 10);
|
||||
matrix.rotate(M_PI / 4);
|
||||
device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap, alpha));
|
||||
device->DrawTransformedBitmapEx(matrix, Bitmap(bitmap, alpha));
|
||||
//savePNG("/tmp/a3.png", device);
|
||||
CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(0, 1)));
|
||||
CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1, 0)));
|
||||
|
||||
@@ -559,19 +559,6 @@ void QtGraphicsBackend::invert(sal_uInt32 /*nPoints*/, const Point* /*pPtAry*/,
|
||||
{
|
||||
}
|
||||
|
||||
static QImage getAlphaImage(const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap)
|
||||
{
|
||||
assert(rSourceBitmap.GetSize() == rAlphaBitmap.GetSize());
|
||||
assert(rAlphaBitmap.GetBitCount() == 8 || rAlphaBitmap.GetBitCount() == 1);
|
||||
|
||||
QImage aAlphaMask = *static_cast<const QtBitmap*>(&rAlphaBitmap)->GetQImage();
|
||||
|
||||
const QImage* pBitmap = static_cast<const QtBitmap*>(&rSourceBitmap)->GetQImage();
|
||||
QImage aImage = pBitmap->convertToFormat(Qt_DefaultFormat32);
|
||||
aImage.setAlphaChannel(aAlphaMask);
|
||||
return aImage;
|
||||
}
|
||||
|
||||
void QtGraphicsBackend::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSourceBitmap)
|
||||
{
|
||||
drawBitmap(rPosAry, rSourceBitmap);
|
||||
@@ -580,14 +567,9 @@ void QtGraphicsBackend::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitm
|
||||
bool QtGraphicsBackend::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha)
|
||||
const SalBitmap& rSourceBitmap, double fAlpha)
|
||||
{
|
||||
QImage aImage;
|
||||
if (!pAlphaBitmap)
|
||||
aImage = *static_cast<const QtBitmap*>(&rSourceBitmap)->GetQImage();
|
||||
else
|
||||
aImage = getAlphaImage(rSourceBitmap, *pAlphaBitmap);
|
||||
QImage aImage = *static_cast<const QtBitmap*>(&rSourceBitmap)->GetQImage();
|
||||
|
||||
const basegfx::B2DVector aXRel = rX - rNull;
|
||||
const basegfx::B2DVector aYRel = rY - rNull;
|
||||
|
||||
@@ -1216,8 +1216,7 @@ void AquaGraphicsBackend::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBi
|
||||
bool AquaGraphicsBackend::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSrcBitmap,
|
||||
const SalBitmap* pAlphaBmp, double fAlpha)
|
||||
const SalBitmap& rSrcBitmap, double fAlpha)
|
||||
{
|
||||
if (!mrShared.checkContext())
|
||||
return true;
|
||||
@@ -1226,14 +1225,9 @@ bool AquaGraphicsBackend::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
return false;
|
||||
|
||||
// get the Quartz image
|
||||
CGImageRef xImage = nullptr;
|
||||
const Size aSize = rSrcBitmap.GetSize();
|
||||
|
||||
if (!pAlphaBmp)
|
||||
xImage = rSrcBitmap.CreateCroppedImage(0, 0, int(aSize.Width()), int(aSize.Height()));
|
||||
else
|
||||
xImage
|
||||
= rSrcBitmap.CreateWithMask(*pAlphaBmp, 0, 0, int(aSize.Width()), int(aSize.Height()));
|
||||
CGImageRef xImage
|
||||
= rSrcBitmap.CreateCroppedImage(0, 0, int(aSize.Width()), int(aSize.Height()));
|
||||
|
||||
if (!xImage)
|
||||
return false;
|
||||
|
||||
+17
-86
@@ -1532,17 +1532,11 @@ void SkiaSalGraphicsImpl::invert(sal_uInt32 nPoints, const Point* pPointArray, S
|
||||
// with the given target size. Result will be possibly cached, unless disabled.
|
||||
// Especially in raster mode scaling and alpha blending may be expensive if done repeatedly.
|
||||
sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitmap,
|
||||
const SkiaSalBitmap* alphaBitmap,
|
||||
const Size& targetSize)
|
||||
{
|
||||
if (alphaBitmap)
|
||||
assert(bitmap.GetSize() == alphaBitmap->GetSize());
|
||||
|
||||
if (targetSize.IsEmpty())
|
||||
return {};
|
||||
if (alphaBitmap && alphaBitmap->IsFullyOpaqueAsAlpha())
|
||||
alphaBitmap = nullptr; // the alpha can be ignored
|
||||
if (bitmap.PreferSkShader() && (!alphaBitmap || alphaBitmap->PreferSkShader()))
|
||||
if (bitmap.PreferSkShader())
|
||||
return {};
|
||||
|
||||
// If the bitmap has SkImage that matches the required size, try to use it, even
|
||||
@@ -1551,48 +1545,18 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
|
||||
// scale, changing GetImageKey() in the process so we'd have to re-cache, and then we'd need
|
||||
// to scale again in this function.
|
||||
bool bitmapReady = false;
|
||||
bool alphaBitmapReady = false;
|
||||
if (const sk_sp<SkImage>& image = bitmap.GetSkImage(DirectImage::Yes))
|
||||
{
|
||||
assert(!bitmap.PreferSkShader());
|
||||
if (imageSize(image) == targetSize)
|
||||
bitmapReady = true;
|
||||
}
|
||||
// If the image usable and there's no alpha, then it matches exactly what's wanted.
|
||||
if (bitmapReady && !alphaBitmap)
|
||||
// If the image usable, then it matches exactly what's wanted.
|
||||
if (bitmapReady)
|
||||
return bitmap.GetSkImage(DirectImage::Yes);
|
||||
if (alphaBitmap)
|
||||
{
|
||||
if (!alphaBitmap->GetAlphaSkImage(DirectImage::Yes)
|
||||
&& alphaBitmap->GetSkImage(DirectImage::Yes)
|
||||
&& imageSize(alphaBitmap->GetSkImage(DirectImage::Yes)) == targetSize)
|
||||
{
|
||||
// There's a usable non-alpha image, try to convert it to alpha.
|
||||
assert(!alphaBitmap->PreferSkShader());
|
||||
const_cast<SkiaSalBitmap*>(alphaBitmap)->TryDirectConvertToAlphaNoScaling();
|
||||
}
|
||||
if (const sk_sp<SkImage>& image = alphaBitmap->GetAlphaSkImage(DirectImage::Yes))
|
||||
{
|
||||
assert(!alphaBitmap->PreferSkShader());
|
||||
if (imageSize(image) == targetSize)
|
||||
alphaBitmapReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bitmapReady && (!alphaBitmap || alphaBitmapReady))
|
||||
{
|
||||
// Try to find a cached image based on the already existing images.
|
||||
OString key = makeCachedImageKey(bitmap, alphaBitmap, targetSize, DirectImage::Yes,
|
||||
DirectImage::Yes);
|
||||
if (sk_sp<SkImage> image = findCachedImage(key))
|
||||
{
|
||||
assert(imageSize(image) == targetSize);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
// Probably not much point in caching of just doing a copy.
|
||||
if (alphaBitmap == nullptr && targetSize == bitmap.GetSize())
|
||||
if (targetSize == bitmap.GetSize())
|
||||
return {};
|
||||
// Image too small to be worth caching if not scaling.
|
||||
if (targetSize == bitmap.GetSize() && targetSize.Width() < 100 && targetSize.Height() < 100)
|
||||
@@ -1616,17 +1580,11 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
|
||||
// that they are the same size, or that one prefers a shader or doesn't exist
|
||||
// (i.e. avoid two images of different size).
|
||||
bitmapReady = bitmap.GetSkImage(DirectImage::Yes) != nullptr;
|
||||
alphaBitmapReady = alphaBitmap && alphaBitmap->GetAlphaSkImage(DirectImage::Yes) != nullptr;
|
||||
if (bitmapReady && alphaBitmap && !alphaBitmapReady && !alphaBitmap->PreferSkShader())
|
||||
bitmapReady = false;
|
||||
if (alphaBitmapReady && !bitmapReady && bitmap.PreferSkShader())
|
||||
alphaBitmapReady = false;
|
||||
|
||||
DirectImage bitmapType = bitmapReady ? DirectImage::Yes : DirectImage::No;
|
||||
DirectImage alphaBitmapType = alphaBitmapReady ? DirectImage::Yes : DirectImage::No;
|
||||
|
||||
// Try to find a cached result, this time after possible delayed scaling.
|
||||
OString key = makeCachedImageKey(bitmap, alphaBitmap, targetSize, bitmapType, alphaBitmapType);
|
||||
OString key = makeCachedImageKey(bitmap, targetSize, bitmapType);
|
||||
if (sk_sp<SkImage> image = findCachedImage(key))
|
||||
{
|
||||
assert(imageSize(image) == targetSize);
|
||||
@@ -1666,14 +1624,11 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
|
||||
Size sourceSize;
|
||||
if (bitmapReady)
|
||||
sourceSize = imageSize(bitmap.GetSkImage(DirectImage::Yes));
|
||||
else if (alphaBitmapReady)
|
||||
sourceSize = imageSize(alphaBitmap->GetAlphaSkImage(DirectImage::Yes));
|
||||
else
|
||||
sourceSize = bitmap.GetSize();
|
||||
|
||||
// Generate a new result and cache it.
|
||||
sk_sp<SkSurface> tmpSurface
|
||||
= createSkSurface(targetSize, alphaBitmap ? kPremul_SkAlphaType : bitmap.alphaType());
|
||||
sk_sp<SkSurface> tmpSurface = createSkSurface(targetSize, bitmap.alphaType());
|
||||
if (!tmpSurface)
|
||||
return nullptr;
|
||||
SkCanvas* canvas = tmpSurface->getCanvas();
|
||||
@@ -1690,12 +1645,10 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
|
||||
if (!isUnitTestRunning()) // unittests want exact pixel values
|
||||
samplingOptions = makeSamplingOptions(matrix, 1);
|
||||
}
|
||||
if (alphaBitmap != nullptr)
|
||||
if (bitmap.alphaType() == kPremul_SkAlphaType)
|
||||
{
|
||||
canvas->clear(SK_ColorTRANSPARENT);
|
||||
paint.setShader(SkShaders::Blend(
|
||||
SkBlendMode::kDstIn, bitmap.GetSkShader(samplingOptions, bitmapType),
|
||||
alphaBitmap->GetAlphaSkShader(samplingOptions, alphaBitmapType)));
|
||||
paint.setShader(bitmap.GetSkShader(samplingOptions, bitmapType));
|
||||
canvas->drawPaint(paint);
|
||||
}
|
||||
else if (bitmap.PreferSkShader())
|
||||
@@ -1715,15 +1668,11 @@ sk_sp<SkImage> SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma
|
||||
return image;
|
||||
}
|
||||
|
||||
OString SkiaSalGraphicsImpl::makeCachedImageKey(const SkiaSalBitmap& bitmap,
|
||||
const SkiaSalBitmap* alphaBitmap,
|
||||
const Size& targetSize, DirectImage bitmapType,
|
||||
DirectImage alphaBitmapType)
|
||||
OString SkiaSalGraphicsImpl::makeCachedImageKey(const SkiaSalBitmap& bitmap, const Size& targetSize,
|
||||
DirectImage bitmapType)
|
||||
{
|
||||
OString key = OString::number(targetSize.Width()) + "x" + OString::number(targetSize.Height())
|
||||
+ "_" + bitmap.GetImageKey(bitmapType);
|
||||
if (alphaBitmap)
|
||||
key += "_" + alphaBitmap->GetAlphaImageKey(alphaBitmapType);
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -1745,7 +1694,7 @@ void SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBi
|
||||
imagePosAry.mnSrcHeight = imagePosAry.mnDestHeight;
|
||||
imageSize = Size(imagePosAry.mnSrcWidth, imagePosAry.mnSrcHeight);
|
||||
}
|
||||
sk_sp<SkImage> image = mergeCacheBitmaps(rSkiaSourceBitmap, nullptr, imageSize * mScaling);
|
||||
sk_sp<SkImage> image = mergeCacheBitmaps(rSkiaSourceBitmap, imageSize * mScaling);
|
||||
if (image)
|
||||
drawImage(imagePosAry, image, mScaling);
|
||||
else
|
||||
@@ -1769,7 +1718,7 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBit
|
||||
imagePosAry.mnSrcHeight = imagePosAry.mnDestHeight;
|
||||
imageSize = Size(imagePosAry.mnSrcWidth, imagePosAry.mnSrcHeight);
|
||||
}
|
||||
sk_sp<SkImage> image = mergeCacheBitmaps(bitmap, nullptr, imageSize * mScaling);
|
||||
sk_sp<SkImage> image = mergeCacheBitmaps(bitmap, imageSize * mScaling);
|
||||
if (image)
|
||||
drawImage(imagePosAry, image, mScaling, blendMode);
|
||||
else if (bitmap.PreferSkShader())
|
||||
@@ -1880,17 +1829,11 @@ bool matrixNeedsHighQuality(const SkMatrix& matrix) { return ::matrixNeedsHighQu
|
||||
bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha)
|
||||
const SalBitmap& rSourceBitmap, double fAlpha)
|
||||
{
|
||||
assert(dynamic_cast<const SkiaSalBitmap*>(&rSourceBitmap));
|
||||
assert(!pAlphaBitmap || dynamic_cast<const SkiaSalBitmap*>(pAlphaBitmap));
|
||||
|
||||
const SkiaSalBitmap& rSkiaBitmap = static_cast<const SkiaSalBitmap&>(rSourceBitmap);
|
||||
const SkiaSalBitmap* pSkiaAlphaBitmap = static_cast<const SkiaSalBitmap*>(pAlphaBitmap);
|
||||
|
||||
if (pSkiaAlphaBitmap && pSkiaAlphaBitmap->IsFullyOpaqueAsAlpha())
|
||||
pSkiaAlphaBitmap = nullptr; // the alpha can be ignored
|
||||
|
||||
// Setup the image transformation,
|
||||
// using the rNull, rX, rY points as destinations for the (0,0), (Width,0), (0,Height) source points.
|
||||
@@ -1909,8 +1852,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
// Pass size * mScaling to mergeCacheBitmaps() so that it prepares the size that will be needed
|
||||
// after the mScaling-scaling matrix, but otherwise calculate everything else using the VCL coordinates.
|
||||
Size imageSize(round(aXRel.getLength()), round(aYRel.getLength()));
|
||||
sk_sp<SkImage> imageToDraw
|
||||
= mergeCacheBitmaps(rSkiaBitmap, pSkiaAlphaBitmap, imageSize * mScaling);
|
||||
sk_sp<SkImage> imageToDraw = mergeCacheBitmaps(rSkiaBitmap, imageSize * mScaling);
|
||||
if (imageToDraw)
|
||||
{
|
||||
SkMatrix matrix;
|
||||
@@ -1968,19 +1910,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
SkSamplingOptions samplingOptions;
|
||||
if (matrixNeedsHighQuality(matrix) || (mScaling != 1 && !isUnitTestRunning()))
|
||||
samplingOptions = makeSamplingOptions(matrix, mScaling);
|
||||
if (pSkiaAlphaBitmap)
|
||||
{
|
||||
SkPaint paint = makeBitmapPaint();
|
||||
paint.setShader(SkShaders::Blend(SkBlendMode::kDstIn,
|
||||
rSkiaBitmap.GetSkShader(samplingOptions),
|
||||
pSkiaAlphaBitmap->GetAlphaSkShader(samplingOptions)));
|
||||
if (fAlpha != 1.0)
|
||||
paint.setShader(
|
||||
SkShaders::Blend(SkBlendMode::kDstIn, paint.refShader(),
|
||||
SkShaders::Color(SkColorSetARGB(fAlpha * 255, 0, 0, 0))));
|
||||
canvas->drawRect(SkRect::MakeWH(aSize.Width(), aSize.Height()), paint);
|
||||
}
|
||||
else if (rSkiaBitmap.PreferSkShader() || fAlpha != 1.0)
|
||||
if (rSkiaBitmap.PreferSkShader() || fAlpha != 1.0)
|
||||
{
|
||||
SkPaint paint = makeBitmapPaint();
|
||||
paint.setShader(rSkiaBitmap.GetSkShader(samplingOptions));
|
||||
@@ -1993,7 +1923,8 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
else
|
||||
{
|
||||
SkPaint paint = makeBitmapPaint();
|
||||
canvas->drawImage(rSkiaBitmap.GetSkImage(), 0, 0, samplingOptions, &paint);
|
||||
paint.setShader(rSkiaBitmap.GetSkShader(samplingOptions));
|
||||
canvas->drawRect(SkRect::MakeWH(aSize.Width(), aSize.Height()), paint);
|
||||
}
|
||||
}
|
||||
postDraw();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <config_features.h>
|
||||
|
||||
#include <rtl/math.hxx>
|
||||
#include <sal/log.hxx>
|
||||
#include <osl/diagnose.h>
|
||||
#include <tools/helpers.hxx>
|
||||
@@ -2719,4 +2720,192 @@ tools::Polygon Bitmap::GetContour( bool bContourEdgeDetect,
|
||||
return aRetPoly;
|
||||
}
|
||||
|
||||
static Bitmap impTransformBitmap(
|
||||
const Bitmap& rSource,
|
||||
const Size& rDestinationSize,
|
||||
const basegfx::B2DHomMatrix& rTransform,
|
||||
bool bSmooth)
|
||||
{
|
||||
Bitmap aDestination(rDestinationSize, rSource.getPixelFormat());
|
||||
BitmapScopedWriteAccess xWrite(aDestination);
|
||||
|
||||
if(xWrite)
|
||||
{
|
||||
BitmapScopedReadAccess xRead(rSource);
|
||||
|
||||
if (xRead)
|
||||
{
|
||||
const Size aDestinationSizePixel(aDestination.GetSizePixel());
|
||||
|
||||
// tdf#157795 set color to black outside of bitmap bounds
|
||||
// Due to commit 81994cb2b8b32453a92bcb011830fcb884f22ff3,
|
||||
// transparent areas are now black instead of white.
|
||||
// tdf#160831 only set outside color to black for alpha masks
|
||||
// The outside color still needs to be white for the content
|
||||
// so only apply the fix for tdf#157795 to the alpha mask.
|
||||
const BitmapColor aOutside(ColorAlpha, 0xff, 0xff, 0xff, 0x00);
|
||||
|
||||
for(tools::Long y(0); y < aDestinationSizePixel.getHeight(); y++)
|
||||
{
|
||||
Scanline pScanline = xWrite->GetScanline( y );
|
||||
for(tools::Long x(0); x < aDestinationSizePixel.getWidth(); x++)
|
||||
{
|
||||
const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
|
||||
|
||||
if(bSmooth)
|
||||
{
|
||||
xWrite->SetPixelOnData(
|
||||
pScanline,
|
||||
x,
|
||||
xRead->GetInterpolatedColorWithFallback(
|
||||
aSourceCoor.getY(),
|
||||
aSourceCoor.getX(),
|
||||
aOutside));
|
||||
}
|
||||
else
|
||||
{
|
||||
// this version does the correct <= 0.0 checks, so no need
|
||||
// to do the static_cast< sal_Int32 > self and make an error
|
||||
xWrite->SetPixelOnData(
|
||||
pScanline,
|
||||
x,
|
||||
xRead->GetColorWithFallback(
|
||||
aSourceCoor.getY(),
|
||||
aSourceCoor.getX(),
|
||||
aOutside));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xWrite.reset();
|
||||
|
||||
rSource.AdaptBitCount(aDestination);
|
||||
|
||||
return aDestination;
|
||||
}
|
||||
|
||||
/// Decides if rTransformation needs smoothing or not (e.g. 180 deg rotation doesn't need it).
|
||||
static bool implTransformNeedsSmooth(const basegfx::B2DHomMatrix& rTransformation)
|
||||
{
|
||||
basegfx::B2DVector aScale, aTranslate;
|
||||
double fRotate, fShearX;
|
||||
rTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
|
||||
if (aScale != basegfx::B2DVector(1, 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
fRotate = fmod( fRotate, 2 * M_PI );
|
||||
if (fRotate < 0)
|
||||
{
|
||||
fRotate += 2 * M_PI;
|
||||
}
|
||||
if (!rtl::math::approxEqual(fRotate, 0)
|
||||
&& !rtl::math::approxEqual(fRotate, M_PI_2)
|
||||
&& !rtl::math::approxEqual(fRotate, M_PI)
|
||||
&& !rtl::math::approxEqual(fRotate, 3 * M_PI_2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!rtl::math::approxEqual(fShearX, 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Bitmap Bitmap::TransformBitmap(
|
||||
double fWidth,
|
||||
double fHeight,
|
||||
const basegfx::B2DHomMatrix& rTransformation) const
|
||||
{
|
||||
if(fWidth <= 1 || fHeight <= 1)
|
||||
return Bitmap();
|
||||
|
||||
// force destination to 24 bit, we want to smooth output
|
||||
const Size aDestinationSize(basegfx::fround<tools::Long>(fWidth), basegfx::fround<tools::Long>(fHeight));
|
||||
bool bSmooth = implTransformNeedsSmooth(rTransformation);
|
||||
const Bitmap aDestination(impTransformBitmap(*this, aDestinationSize, rTransformation, bSmooth));
|
||||
|
||||
return aDestination;
|
||||
}
|
||||
|
||||
Bitmap Bitmap::getTransformed(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const basegfx::B2DRange& rVisibleRange,
|
||||
double fMaximumArea) const
|
||||
{
|
||||
if (IsEmpty())
|
||||
return Bitmap();
|
||||
|
||||
const sal_uInt32 nSourceWidth(GetSizePixel().Width());
|
||||
const sal_uInt32 nSourceHeight(GetSizePixel().Height());
|
||||
|
||||
if (!nSourceWidth || !nSourceHeight)
|
||||
return Bitmap();
|
||||
|
||||
// Get aOutlineRange
|
||||
basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
|
||||
|
||||
aOutlineRange.transform(rTransformation);
|
||||
|
||||
// create visible range from it by moving from relative to absolute
|
||||
basegfx::B2DRange aVisibleRange(rVisibleRange);
|
||||
|
||||
aVisibleRange.transform(
|
||||
basegfx::utils::createScaleTranslateB2DHomMatrix(
|
||||
aOutlineRange.getRange(),
|
||||
aOutlineRange.getMinimum()));
|
||||
|
||||
// get target size (which is visible range's size)
|
||||
double fWidth(aVisibleRange.getWidth());
|
||||
double fHeight(aVisibleRange.getHeight());
|
||||
|
||||
if (fWidth < 1.0 || fHeight < 1.0)
|
||||
return Bitmap();
|
||||
|
||||
// test if discrete size (pixel) maybe too big and limit it
|
||||
const double fArea(fWidth * fHeight);
|
||||
const bool bNeedToReduce(basegfx::fTools::more(fArea, fMaximumArea));
|
||||
double fReduceFactor(1.0);
|
||||
|
||||
if(bNeedToReduce)
|
||||
{
|
||||
fReduceFactor = sqrt(fMaximumArea / fArea);
|
||||
fWidth *= fReduceFactor;
|
||||
fHeight *= fReduceFactor;
|
||||
}
|
||||
|
||||
// Build complete transform from source pixels to target pixels.
|
||||
// Start by scaling from source pixel size to unit coordinates
|
||||
basegfx::B2DHomMatrix aTransform(
|
||||
basegfx::utils::createScaleB2DHomMatrix(
|
||||
1.0 / nSourceWidth,
|
||||
1.0 / nSourceHeight));
|
||||
|
||||
// multiply with given transform which leads from unit coordinates inside
|
||||
// aOutlineRange
|
||||
aTransform = rTransformation * aTransform;
|
||||
|
||||
// subtract top-left of absolute VisibleRange
|
||||
aTransform.translate(
|
||||
-aVisibleRange.getMinX(),
|
||||
-aVisibleRange.getMinY());
|
||||
|
||||
// scale to target pixels (if needed)
|
||||
if(bNeedToReduce)
|
||||
{
|
||||
aTransform.scale(fReduceFactor, fReduceFactor);
|
||||
}
|
||||
|
||||
// invert to get transformation from target pixel coordinates to source pixels
|
||||
aTransform.invert();
|
||||
|
||||
// create bitmap using source, destination and linear back-transformation
|
||||
return TransformBitmap(fWidth, fHeight, aTransform);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
||||
@@ -171,7 +171,7 @@ void Printer::ImplPrintTransparent( const Bitmap& rBmp,
|
||||
|
||||
bool Printer::DrawTransformBitmapExDirect(
|
||||
const basegfx::B2DHomMatrix& /*aFullTransform*/,
|
||||
const BitmapEx& /*rBitmapEx*/,
|
||||
const Bitmap& /*rBitmap*/,
|
||||
double /*fAlpha*/)
|
||||
{
|
||||
// printers can't draw bitmaps directly
|
||||
|
||||
@@ -90,7 +90,6 @@ bool SalGraphics::drawTransformedBitmap(
|
||||
const basegfx::B2DPoint& /* rX */,
|
||||
const basegfx::B2DPoint& /* rY */,
|
||||
const SalBitmap& /* rSourceBitmap */,
|
||||
const SalBitmap* /* pAlphaBitmap */,
|
||||
double /* fAlpha */)
|
||||
{
|
||||
// here direct support for transformed bitmaps can be implemented
|
||||
@@ -841,7 +840,6 @@ bool SalGraphics::DrawTransformedBitmap(
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha,
|
||||
const OutputDevice& rOutDev)
|
||||
{
|
||||
@@ -859,11 +857,11 @@ bool SalGraphics::DrawTransformedBitmap(
|
||||
basegfx::B2DPoint aX = aTranslateToMirroredBounds * rX;
|
||||
basegfx::B2DPoint aY = aTranslateToMirroredBounds * rY;
|
||||
|
||||
return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap, fAlpha);
|
||||
return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, fAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha);
|
||||
return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, fAlpha);
|
||||
}
|
||||
|
||||
bool SalGraphics::HasFastDrawTransformedBitmap() const
|
||||
|
||||
@@ -186,7 +186,7 @@ void OutputDevice::DrawDeviceBitmapEx( const Point& rDestPt, const Size& rDestSi
|
||||
|
||||
bool OutputDevice::DrawTransformBitmapExDirect(
|
||||
const basegfx::B2DHomMatrix& aFullTransform,
|
||||
const BitmapEx& rBitmapEx,
|
||||
const Bitmap& rBitmap,
|
||||
double fAlpha)
|
||||
{
|
||||
assert(!is_double_buffered_window());
|
||||
@@ -195,22 +195,13 @@ bool OutputDevice::DrawTransformBitmapExDirect(
|
||||
const basegfx::B2DPoint aNull(aFullTransform * basegfx::B2DPoint(0.0, 0.0));
|
||||
const basegfx::B2DPoint aTopX(aFullTransform * basegfx::B2DPoint(1.0, 0.0));
|
||||
const basegfx::B2DPoint aTopY(aFullTransform * basegfx::B2DPoint(0.0, 1.0));
|
||||
SalBitmap* pSalSrcBmp = rBitmapEx.GetBitmap().ImplGetSalBitmap().get();
|
||||
AlphaMask aAlphaBitmap;
|
||||
|
||||
if(rBitmapEx.IsAlpha())
|
||||
{
|
||||
aAlphaBitmap = rBitmapEx.GetAlphaMask();
|
||||
}
|
||||
|
||||
SalBitmap* pSalAlphaBmp = aAlphaBitmap.GetBitmap().ImplGetSalBitmap().get();
|
||||
SalBitmap* pSalSrcBmp = rBitmap.ImplGetSalBitmap().get();
|
||||
|
||||
return mpGraphics->DrawTransformedBitmap(
|
||||
aNull,
|
||||
aTopX,
|
||||
aTopY,
|
||||
*pSalSrcBmp,
|
||||
pSalAlphaBmp,
|
||||
fAlpha,
|
||||
*this);
|
||||
};
|
||||
@@ -326,21 +317,13 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const Bitmap& rBitmap,
|
||||
double fAlpha)
|
||||
{
|
||||
DrawTransformedBitmapEx(rTransformation, BitmapEx(rBitmap), fAlpha);
|
||||
}
|
||||
|
||||
void OutputDevice::DrawTransformedBitmapEx(
|
||||
const basegfx::B2DHomMatrix& rTransformation,
|
||||
const BitmapEx& rBitmapEx,
|
||||
double fAlpha)
|
||||
{
|
||||
assert(!is_double_buffered_window());
|
||||
|
||||
if( ImplIsRecordLayout() )
|
||||
return;
|
||||
|
||||
if(rBitmapEx.IsEmpty())
|
||||
if(rBitmap.IsEmpty())
|
||||
return;
|
||||
|
||||
if( fAlpha == 0.0 )
|
||||
@@ -378,7 +361,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
: nullptr);
|
||||
#endif
|
||||
|
||||
BitmapEx bitmapEx = rBitmapEx;
|
||||
Bitmap bitmap = rBitmap;
|
||||
|
||||
const bool bInvert(RasterOp::Invert == meRasterOp);
|
||||
const bool bBitmapChangedColor(mnDrawMode & (DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap | DrawModeFlags::GrayBitmap ));
|
||||
@@ -393,7 +376,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
{
|
||||
if(bTryDirectPaint)
|
||||
{
|
||||
if(DrawTransformBitmapExDirect(aFullTransform, bitmapEx, fAlpha))
|
||||
if(DrawTransformBitmapExDirect(aFullTransform, bitmap, fAlpha))
|
||||
{
|
||||
// we are done
|
||||
return;
|
||||
@@ -401,15 +384,15 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
}
|
||||
// Apply the alpha manually.
|
||||
sal_uInt8 nTransparency( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
|
||||
AlphaMask aAlpha( bitmapEx.GetSizePixel(), &nTransparency );
|
||||
if( bitmapEx.IsAlpha())
|
||||
aAlpha.BlendWith( bitmapEx.GetAlphaMask());
|
||||
bitmapEx = BitmapEx( bitmapEx.GetBitmap(), aAlpha );
|
||||
AlphaMask aAlpha( bitmap.GetSizePixel(), &nTransparency );
|
||||
if( bitmap.HasAlpha())
|
||||
aAlpha.BlendWith( bitmap.CreateAlphaMask());
|
||||
bitmap = Bitmap( bitmap.CreateColorBitmap(), aAlpha );
|
||||
}
|
||||
|
||||
// If the backend's implementation is known to not need any optimizations here, pass to it directly.
|
||||
// With most backends it's more performant to try to simplify to DrawBitmapEx() first.
|
||||
if(bTryDirectPaint && mpGraphics->HasFastDrawTransformedBitmap() && DrawTransformBitmapExDirect(aFullTransform, bitmapEx))
|
||||
if(bTryDirectPaint && mpGraphics->HasFastDrawTransformedBitmap() && DrawTransformBitmapExDirect(aFullTransform, bitmap))
|
||||
return;
|
||||
|
||||
// decompose matrix to check rotation and shear
|
||||
@@ -437,7 +420,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
EnableMapMode(false);
|
||||
}
|
||||
|
||||
DrawBitmapEx(aDestPt, aDestSize, Bitmap(bitmapEx));
|
||||
DrawBitmapEx(aDestPt, aDestSize, bitmap);
|
||||
if (!bMetafile && comphelper::LibreOfficeKit::isActive() && GetMapMode().GetMapUnit() != MapUnit::MapPixel)
|
||||
{
|
||||
EnableMapMode();
|
||||
@@ -447,7 +430,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
}
|
||||
|
||||
// Try the backend's implementation before resorting to the slower fallback here.
|
||||
if(bTryDirectPaint && DrawTransformBitmapExDirect(aFullTransform, bitmapEx))
|
||||
if(bTryDirectPaint && DrawTransformBitmapExDirect(aFullTransform, bitmap))
|
||||
return;
|
||||
|
||||
// take the fallback when no rotate and shear, but mirror (else we would have done this above)
|
||||
@@ -461,7 +444,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
basegfx::fround<tools::Long>(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
|
||||
basegfx::fround<tools::Long>(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
|
||||
|
||||
DrawBitmapEx(aDestPt, aDestSize, Bitmap(bitmapEx));
|
||||
DrawBitmapEx(aDestPt, aDestSize, bitmap);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -476,8 +459,8 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
// by using a fixed minimum (allow at least, but no need to utilize) for good smoothing and an area
|
||||
// dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
|
||||
// to avoid crashes/resource problems (ca. 1500x3000 here)
|
||||
const Size& rOriginalSizePixel(bitmapEx.GetSizePixel());
|
||||
const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
|
||||
const Size aOriginalSizePixel(bitmap.GetSizePixel());
|
||||
const double fOrigArea(aOriginalSizePixel.Width() * aOriginalSizePixel.Height() * 0.5);
|
||||
const double fOrigAreaScaled(fOrigArea * 1.44);
|
||||
double fMaximumArea(std::clamp(fOrigAreaScaled, 1000000.0, 4500000.0));
|
||||
|
||||
@@ -490,20 +473,20 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
if(aVisibleRange.isEmpty())
|
||||
return;
|
||||
|
||||
BitmapEx aTransformed(bitmapEx);
|
||||
Bitmap aTransformed(bitmap);
|
||||
|
||||
// #122923# when the result needs an alpha channel due to being rotated or sheared
|
||||
// and thus uncovering areas, add these channels so that the own transformer (used
|
||||
// in getTransformed) also creates a transformed alpha channel
|
||||
if(!aTransformed.IsAlpha() && (bSheared || bRotated))
|
||||
if(!aTransformed.HasAlpha() && (bSheared || bRotated))
|
||||
{
|
||||
// parts will be uncovered, extend aTransformed with a mask bitmap
|
||||
const Bitmap aContent(aTransformed.GetBitmap());
|
||||
const Bitmap aContent(aTransformed.CreateColorBitmap());
|
||||
|
||||
AlphaMask aMaskBmp(aContent.GetSizePixel());
|
||||
aMaskBmp.Erase(0);
|
||||
|
||||
aTransformed = BitmapEx(aContent, aMaskBmp);
|
||||
aTransformed = Bitmap(aContent, aMaskBmp);
|
||||
}
|
||||
|
||||
basegfx::B2DVector aFullScale, aFullTranslate;
|
||||
@@ -511,9 +494,9 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
aFullTransform.decompose(aFullScale, aFullTranslate, fFullRotate, fFullShearX);
|
||||
|
||||
double fSourceRatio = 1.0;
|
||||
if (rOriginalSizePixel.getHeight() != 0)
|
||||
if (aOriginalSizePixel.getHeight() != 0)
|
||||
{
|
||||
fSourceRatio = rOriginalSizePixel.getWidth() / rOriginalSizePixel.getHeight();
|
||||
fSourceRatio = aOriginalSizePixel.getWidth() / aOriginalSizePixel.getHeight();
|
||||
}
|
||||
double fTargetRatio = 1.0;
|
||||
if (aFullScale.getY() != 0)
|
||||
@@ -558,7 +541,7 @@ void OutputDevice::DrawTransformedBitmapEx(
|
||||
basegfx::fround<tools::Long>(aVisibleRange.getMaxX()) - aDestPt.X(),
|
||||
basegfx::fround<tools::Long>(aVisibleRange.getMaxY()) - aDestPt.Y());
|
||||
|
||||
DrawBitmapEx(aDestPt, aDestSize, Bitmap(aTransformed));
|
||||
DrawBitmapEx(aDestPt, aDestSize, aTransformed);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
||||
|
||||
@@ -204,10 +204,9 @@ bool X11CairoSalGraphicsImpl::drawPolyPolygonBezier(sal_uInt32, const sal_uInt32
|
||||
bool X11CairoSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha)
|
||||
const SalBitmap& rSourceBitmap, double fAlpha)
|
||||
{
|
||||
return mrCairoCommon.drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha,
|
||||
return mrCairoCommon.drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, fAlpha,
|
||||
getAntiAlias());
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
/** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
|
||||
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap, double fAlpha) override;
|
||||
double fAlpha) override;
|
||||
|
||||
bool supportsOperation(OutDevSupportType eType) const override;
|
||||
};
|
||||
|
||||
@@ -2342,18 +2342,15 @@ bool WinSalGraphicsImpl::drawTransformedBitmap(
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha)
|
||||
{
|
||||
assert(dynamic_cast<const WinSalBitmap*>(&rSourceBitmap));
|
||||
assert(!pAlphaBitmap || dynamic_cast<const WinSalBitmap*>(pAlphaBitmap));
|
||||
|
||||
if( fAlpha != 1.0 )
|
||||
return false;
|
||||
|
||||
const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSourceBitmap);
|
||||
const WinSalBitmap* pSalAlpha = static_cast< const WinSalBitmap* >(pAlphaBitmap);
|
||||
std::shared_ptr< Gdiplus::Bitmap > aARGB(rSalBitmap.ImplGetGdiPlusBitmap(pSalAlpha));
|
||||
std::shared_ptr< Gdiplus::Bitmap > aARGB(rSalBitmap.ImplGetGdiPlusBitmap());
|
||||
|
||||
if(!aARGB)
|
||||
return false;
|
||||
|
||||
@@ -192,7 +192,6 @@ public:
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha) override;
|
||||
|
||||
virtual bool hasFastDrawTransformedBitmap() const override;
|
||||
|
||||
+5
-39
@@ -74,14 +74,11 @@ class SystemDependentData_GdiPlusBitmap : public basegfx::SystemDependentData
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<Gdiplus::Bitmap> mpGdiPlusBitmap;
|
||||
const WinSalBitmap* mpAssociatedAlpha;
|
||||
|
||||
public:
|
||||
SystemDependentData_GdiPlusBitmap(
|
||||
const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap,
|
||||
const WinSalBitmap* pAssociatedAlpha);
|
||||
const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap);
|
||||
|
||||
const WinSalBitmap* getAssociatedAlpha() const { return mpAssociatedAlpha; }
|
||||
const std::shared_ptr<Gdiplus::Bitmap>& getGdiPlusBitmap() const { return mpGdiPlusBitmap; }
|
||||
|
||||
virtual sal_Int64 estimateUsageInBytes() const override;
|
||||
@@ -90,13 +87,11 @@ public:
|
||||
}
|
||||
|
||||
SystemDependentData_GdiPlusBitmap::SystemDependentData_GdiPlusBitmap(
|
||||
const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap,
|
||||
const WinSalBitmap* pAssociatedAlpha)
|
||||
const std::shared_ptr<Gdiplus::Bitmap>& rGdiPlusBitmap)
|
||||
: basegfx::SystemDependentData(
|
||||
Application::GetSystemDependentDataManager(),
|
||||
basegfx::SDD_Type::SDDType_GdiPlusBitmap),
|
||||
mpGdiPlusBitmap(rGdiPlusBitmap),
|
||||
mpAssociatedAlpha(pAssociatedAlpha)
|
||||
mpGdiPlusBitmap(rGdiPlusBitmap)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,7 +146,7 @@ sal_Int64 SystemDependentData_GdiPlusBitmap::estimateUsageInBytes() const
|
||||
return nRetval;
|
||||
}
|
||||
|
||||
std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinSalBitmap* pAlphaSource) const
|
||||
std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap() const
|
||||
{
|
||||
std::shared_ptr< Gdiplus::Bitmap > aRetval;
|
||||
|
||||
@@ -159,20 +154,6 @@ std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinS
|
||||
std::shared_ptr<SystemDependentData_GdiPlusBitmap> pSystemDependentData_GdiPlusBitmap(
|
||||
getSystemDependentData<SystemDependentData_GdiPlusBitmap>(basegfx::SDD_Type::SDDType_GdiPlusBitmap));
|
||||
|
||||
if(pSystemDependentData_GdiPlusBitmap)
|
||||
{
|
||||
// check data validity
|
||||
if(pSystemDependentData_GdiPlusBitmap->getAssociatedAlpha() != pAlphaSource
|
||||
|| 0 == maSize.Width()
|
||||
|| 0 == maSize.Height())
|
||||
{
|
||||
// #122350# if associated alpha with which the GDIPlus was constructed has changed
|
||||
// it is necessary to remove it from buffer, reset reference to it and reconstruct
|
||||
// data invalid, forget
|
||||
pSystemDependentData_GdiPlusBitmap.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if(pSystemDependentData_GdiPlusBitmap)
|
||||
{
|
||||
// use from buffer
|
||||
@@ -180,24 +161,9 @@ std::shared_ptr< Gdiplus::Bitmap > WinSalBitmap::ImplGetGdiPlusBitmap(const WinS
|
||||
}
|
||||
else if(!maSize.IsEmpty())
|
||||
{
|
||||
// create and set data
|
||||
const WinSalBitmap* pAssociatedAlpha(nullptr);
|
||||
|
||||
if(pAlphaSource)
|
||||
{
|
||||
aRetval = const_cast< WinSalBitmap* >(this)->ImplCreateGdiPlusBitmap(*pAlphaSource);
|
||||
pAssociatedAlpha = pAlphaSource;
|
||||
}
|
||||
else
|
||||
{
|
||||
aRetval = const_cast< WinSalBitmap* >(this)->ImplCreateGdiPlusBitmap();
|
||||
pAssociatedAlpha = nullptr;
|
||||
}
|
||||
|
||||
// add to buffering mechanism
|
||||
addOrReplaceSystemDependentData<SystemDependentData_GdiPlusBitmap>(
|
||||
aRetval,
|
||||
pAssociatedAlpha);
|
||||
aRetval);
|
||||
}
|
||||
|
||||
return aRetval;
|
||||
|
||||
@@ -79,11 +79,10 @@ bool WinSalGraphics::drawTransformedBitmap(
|
||||
const basegfx::B2DPoint& rX,
|
||||
const basegfx::B2DPoint& rY,
|
||||
const SalBitmap& rSourceBitmap,
|
||||
const SalBitmap* pAlphaBitmap,
|
||||
double fAlpha)
|
||||
{
|
||||
return mpImpl->drawTransformedBitmap(rNull, rX, rY,
|
||||
rSourceBitmap, pAlphaBitmap, fAlpha);
|
||||
rSourceBitmap, fAlpha);
|
||||
}
|
||||
|
||||
bool WinSalGraphics::hasFastDrawTransformedBitmap() const
|
||||
|
||||
Reference in New Issue
Block a user