diff options
-rw-r--r-- | cppcanvas/source/mtfrenderer/transparencygroupaction.cxx | 67 | ||||
-rw-r--r-- | include/vcl/outdev.hxx | 5 | ||||
-rw-r--r-- | vcl/source/outdev/transparent.cxx | 28 |
3 files changed, 86 insertions, 14 deletions
diff --git a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx index b8350a8f3944..e0caeaa7cf2a 100644 --- a/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx +++ b/cppcanvas/source/mtfrenderer/transparencygroupaction.cxx @@ -205,6 +205,8 @@ namespace cppcanvas::internal return false; } + ::Point aMtfOffsetPoint; + // if there's no buffer bitmap, or as soon as the // total transformation changes, we've got to // re-render the bitmap @@ -215,15 +217,59 @@ namespace cppcanvas::internal { DBG_TESTSOLARMUTEX(); + // tdf#150610 fix broken rendering of text meta actions + // Even when drawing to a VirtualDevice where antialiasing + // is disabled, text will still be drawn with some + // antialiased pixels on HiDPI displays. So, expand the + // size of the VirtualDevice slightly to capture any of + // the pixles drawn past the edges of the destination + // bounds. + bool bHasTextActions = false; + MetaAction* pCurrAct; + int nCurrActionIndex; + for( nCurrActionIndex=0, pCurrAct=mpGroupMtf->FirstAction(); + pCurrAct && !bHasTextActions; + ++nCurrActionIndex, pCurrAct = mpGroupMtf->NextAction() ) + { + switch( pCurrAct->GetType() ) + { + case MetaActionType::TEXT: + case MetaActionType::TEXTARRAY: + case MetaActionType::STRETCHTEXT: + case MetaActionType::TEXTRECT: + if( ( rSubset.mnSubsetBegin == 0 && rSubset.mnSubsetEnd == -1 ) || ( rSubset.mnSubsetBegin <= nCurrActionIndex && rSubset.mnSubsetEnd > nCurrActionIndex ) ) + bHasTextActions = true; + break; + default: + break; + } + } + // output size of metafile ::Size aOutputSizePixel( ::basegfx::fround( aScale.getX() * maDstSize.getWidth() ), ::basegfx::fround( aScale.getY() * maDstSize.getHeight() ) ); - // pixel size of cache bitmap: round up to nearest int - ::Size aBitmapSizePixel( static_cast<sal_Int32>( aScale.getX() * maDstSize.getWidth() )+1, - static_cast<sal_Int32>( aScale.getY() * maDstSize.getHeight() )+1 ); + sal_Int32 nBitmapExtra; + if ( bHasTextActions ) + { + nBitmapExtra = 10; + aMtfOffsetPoint = ::Point( nBitmapExtra / 2, nBitmapExtra / 2 ); + } + else + { + // Related tdf#150610 assume antialiasing is enabled + // Although antialiasing is normally disabled in the + // VirtualDevice, lines in tdf#150610 will draw past + // the edge of the VirtualDevice when running a + // slideshow so always add an extra pixel on the + // right and bottom edges. + nBitmapExtra = 1; + } - ::Point aEmptyPoint; + // pixel size of cache bitmap: round up to nearest int + ::Point aBitmapPoint; + ::Size aBitmapSizePixel( static_cast<sal_Int32>( aScale.getX() * maDstSize.getWidth() ) + nBitmapExtra, + static_cast<sal_Int32>( aScale.getY() * maDstSize.getHeight() ) + nBitmapExtra ); // render our content into an appropriately sized // VirtualDevice with alpha channel @@ -238,8 +284,6 @@ namespace cppcanvas::internal // true subset - extract referenced // metaactions from mpGroupMtf GDIMetaFile aMtf; - MetaAction* pCurrAct; - int nCurrActionIndex; // extract subset actions for( nCurrActionIndex=0, @@ -320,7 +364,9 @@ namespace cppcanvas::internal } aVDev->DrawTransparent( aMtf, - aEmptyPoint, + aBitmapPoint, + aBitmapSizePixel, + aMtfOffsetPoint, aOutputSizePixel, *mpAlphaGradient ); } @@ -328,7 +374,9 @@ namespace cppcanvas::internal { // no subsetting - render whole mtf aVDev->DrawTransparent( *mpGroupMtf, - aEmptyPoint, + aBitmapPoint, + aBitmapSizePixel, + aMtfOffsetPoint, aOutputSizePixel, *mpAlphaGradient ); } @@ -338,7 +386,7 @@ namespace cppcanvas::internal BitmapSharedPtr aBmp( VCLFactory::createBitmap( mpCanvas, aVDev->GetBitmapEx( - aEmptyPoint, + aBitmapPoint, aBitmapSizePixel ) ) ); mxBufferBitmap = aBmp->getUNOBitmap(); maLastTransformation = aTotalTransform; @@ -362,6 +410,7 @@ namespace cppcanvas::internal // the contained scaling, we've got to right-multiply with // the inverse. ::basegfx::B2DHomMatrix aScaleCorrection; + aScaleCorrection.translate( -aMtfOffsetPoint.X(), -aMtfOffsetPoint.Y() ); aScaleCorrection.scale( 1/aScale.getX(), 1/aScale.getY() ); aTransform = aTransform * aScaleCorrection; diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index f3d2e912d0a6..898939978daa 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1499,6 +1499,11 @@ public: const GDIMetaFile& rMtf, const Point& rPos, const Size& rSize, const Gradient& rTransparenceGradient ); + void DrawTransparent( + const GDIMetaFile& rMtf, const Point& rPos, const Size& rSize, + const Point& rMtfPos, const Size& rMtfSize, + const Gradient& rTransparenceGradient ); + protected: virtual void EmulateDrawTransparent( const tools::PolyPolygon& rPolyPoly, sal_uInt16 nTransparencePercent ); diff --git a/vcl/source/outdev/transparent.cxx b/vcl/source/outdev/transparent.cxx index f26ca5439982..11f89efc7a27 100644 --- a/vcl/source/outdev/transparent.cxx +++ b/vcl/source/outdev/transparent.cxx @@ -557,6 +557,13 @@ void OutputDevice::DrawTransparent( const tools::PolyPolygon& rPolyPoly, void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, const Size& rSize, const Gradient& rTransparenceGradient ) { + DrawTransparent( rMtf, rPos, rSize, rPos, rSize, rTransparenceGradient ); +} + +void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, const Size& rSize, + const Point& rMtfPos, const Size& rMtfSize, + const Gradient& rTransparenceGradient ) +{ assert(!is_double_buffered_window()); const Color aBlack( COL_BLACK ); @@ -574,7 +581,7 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, ( mnDrawMode & DrawModeFlags::NoTransparency ) ) { const_cast<GDIMetaFile&>(rMtf).WindStart(); - const_cast<GDIMetaFile&>(rMtf).Play(*this, rPos, rSize); + const_cast<GDIMetaFile&>(rMtf).Play(*this, rMtfPos, rMtfSize); const_cast<GDIMetaFile&>(rMtf).WindStart(); } else @@ -599,7 +606,13 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, if( xVDev->SetOutputSizePixel( aDstRect.GetSize(), true, true ) ) { - if(GetAntialiasing() != AntialiasingFlags::NONE) + // tdf#150610 fix broken rendering of text meta actions + // Even when drawing to a VirtualDevice that has antialiasing + // disabled, text will still be drawn with some antialiased + // pixels on HiDPI displays. So, use the antialiasing enabled + // code to render if there are any text meta actions in the + // metafile. + if(GetAntialiasing() != AntialiasingFlags::NONE || rPos != rMtfPos || rSize != rMtfSize) { // #i102109# // For MetaFile replay (see task) it may now be necessary to take @@ -630,7 +643,7 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, // draw MetaFile to buffer xVDev->EnableMapMode(bBufferMapModeEnabled); const_cast<GDIMetaFile&>(rMtf).WindStart(); - const_cast<GDIMetaFile&>(rMtf).Play(*xVDev, rPos, rSize); + const_cast<GDIMetaFile&>(rMtf).Play(*xVDev, rMtfPos, rMtfSize); const_cast<GDIMetaFile&>(rMtf).WindStart(); // get content bitmap from buffer @@ -641,6 +654,11 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, // create alpha mask from gradient and get as Bitmap xVDev->EnableMapMode(bBufferMapModeEnabled); xVDev->SetDrawMode(DrawModeFlags::GrayGradient); + // Related tdf#150610 draw gradient to VirtualDevice bounds + // If we are here and the metafile bounds differs from the + // VirtualDevice bounds so that we apply the transparency + // gradient to any pixels drawn outside of the metafile + // bounds. xVDev->DrawGradient(tools::Rectangle(rPos, rSize), rTransparenceGradient); xVDev->SetDrawMode(DrawModeFlags::Default); xVDev->EnableMapMode(false); @@ -670,7 +688,7 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, // create paint bitmap const_cast<GDIMetaFile&>(rMtf).WindStart(); - const_cast<GDIMetaFile&>(rMtf).Play(*xVDev, rPos, rSize); + const_cast<GDIMetaFile&>(rMtf).Play(*xVDev, rMtfPos, rMtfSize); const_cast<GDIMetaFile&>(rMtf).WindStart(); xVDev->EnableMapMode( false ); BitmapEx aPaint = xVDev->GetBitmapEx(Point(), xVDev->GetOutputSizePixel()); @@ -678,7 +696,7 @@ void OutputDevice::DrawTransparent( const GDIMetaFile& rMtf, const Point& rPos, // create alpha mask from gradient xVDev->SetDrawMode( DrawModeFlags::GrayGradient ); - xVDev->DrawGradient( tools::Rectangle( rPos, rSize ), rTransparenceGradient ); + xVDev->DrawGradient( tools::Rectangle( rMtfPos, rMtfSize ), rTransparenceGradient ); xVDev->SetDrawMode( DrawModeFlags::Default ); xVDev->EnableMapMode( false ); |