From 0f5368434ef506aadfbd44613b7b98270e6a00c7 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Tue, 3 Sep 2013 13:31:51 +0200 Subject: vcl/pdfwriter: export linear/axial gradients as PDF gradients Using PDF's Axial shading leads to better visual result than Sampled function shading. Only GradientStyle_LINEAR and GradientStyle_AXIAL are affected by this change, all other gradient styles are exported as before. Change-Id: Ib4d549987e34b7ba5d1c5adaf30908f2e306d07e Reviewed-on: https://gerrit.libreoffice.org/5799 Reviewed-by: Michael Meeks Tested-by: Michael Meeks --- vcl/source/gdi/pdfwriter.cxx | 13 ++++ vcl/source/gdi/pdfwriter_impl.cxx | 153 +++++++++++++++++++++++++++++++------ vcl/source/gdi/pdfwriter_impl2.cxx | 62 ++++++++++----- 3 files changed, 186 insertions(+), 42 deletions(-) diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx index 137319ae80b0..fba8f18779cc 100644 --- a/vcl/source/gdi/pdfwriter.cxx +++ b/vcl/source/gdi/pdfwriter.cxx @@ -192,6 +192,19 @@ void PDFWriter::DrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch ) pImplementation->drawHatch( rPolyPoly, rHatch ); } +void PDFWriter::DrawGradient( const Rectangle& rRect, const Gradient& rGradient ) +{ + pImplementation->drawGradient( rRect, rGradient ); +} + +void PDFWriter::DrawGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient ) +{ + pImplementation->push(PUSH_CLIPREGION); + pImplementation->setClipRegion( rPolyPoly.getB2DPolyPolygon() ); + pImplementation->drawGradient( rPolyPoly.GetBoundRect(), rGradient ); + pImplementation->pop(); +} + void PDFWriter::DrawWallpaper( const Rectangle& rRect, const Wallpaper& rWallpaper ) { pImplementation->drawWallpaper( rRect, rWallpaper ); diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 9b720c2c4de3..e3d9ecfd06fa 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -9455,6 +9455,12 @@ bool PDFWriterImpl::writeTransparentObject( TransparencyEmit& rObject ) bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject ) { + // LO internal gradient -> PDF shading type: + // * GradientStyle_LINEAR: axial shading, using sampled-function with 2 samples + // [t=0:colorStart, t=1:colorEnd] + // * GradientStyle_AXIAL: axial shading, using sampled-function with 3 samples + // [t=0:colorEnd, t=0.5:colorStart, t=1:colorEnd] + // * other styles: function shading with aSize.Width() * aSize.Height() samples sal_Int32 nFunctionObject = createObject(); CHECK_RETURN( updateObject( nFunctionObject ) ); @@ -9480,12 +9486,30 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject ) OStringBuffer aLine( 120 ); aLine.append( nFunctionObject ); aLine.append( " 0 obj\n" - "<= 0; y-- ) + sal_uInt8 aCol[3]; + switch (rObject.m_aGradient.GetStyle()) { - for( int x = 0; x < aSize.Width(); x++ ) + case GradientStyle::GradientStyle_AXIAL: + aCol[0] = rObject.m_aGradient.GetEndColor().GetRed(); + aCol[1] = rObject.m_aGradient.GetEndColor().GetGreen(); + aCol[2] = rObject.m_aGradient.GetEndColor().GetBlue(); + CHECK_RETURN( writeBuffer( aCol, 3 ) ); + case GradientStyle::GradientStyle_LINEAR: { - sal_uInt8 aCol[3]; - BitmapColor aColor = pAccess->GetColor( y, x ); - aCol[0] = aColor.GetRed(); - aCol[1] = aColor.GetGreen(); - aCol[2] = aColor.GetBlue(); + aCol[0] = rObject.m_aGradient.GetStartColor().GetRed(); + aCol[1] = rObject.m_aGradient.GetStartColor().GetGreen(); + aCol[2] = rObject.m_aGradient.GetStartColor().GetBlue(); CHECK_RETURN( writeBuffer( aCol, 3 ) ); + + aCol[0] = rObject.m_aGradient.GetEndColor().GetRed(); + aCol[1] = rObject.m_aGradient.GetEndColor().GetGreen(); + aCol[2] = rObject.m_aGradient.GetEndColor().GetBlue(); + CHECK_RETURN( writeBuffer( aCol, 3 ) ); + break; } + default: + for( int y = aSize.Height()-1; y >= 0; y-- ) + { + for( int x = 0; x < aSize.Width(); x++ ) + { + BitmapColor aColor = pAccess->GetColor( y, x ); + aCol[0] = aColor.GetRed(); + aCol[1] = aColor.GetGreen(); + aCol[2] = aColor.GetBlue(); + CHECK_RETURN( writeBuffer( aCol, 3 ) ); + } + } } endCompression(); disableStreamEncryption(); @@ -9539,17 +9585,76 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject ) CHECK_RETURN( updateObject( rObject.m_nObject ) ); aLine.setLength( 0 ); aLine.append( rObject.m_nObject ); - aLine.append( " 0 obj\n" - "<>\n" diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index 2c3df1504887..0fd93adcb00c 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -41,14 +41,14 @@ #include -#undef USE_PDFGRADIENTS - using namespace vcl; using namespace rtl; using namespace com::sun::star; using namespace com::sun::star::uno; using namespace com::sun::star::beans; +static bool lcl_canUsePDFAxialShading(const Gradient& rGradient); + // ----------------------------------------------------------------------------- void PDFWriterImpl::implWriteGradient( const PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient, @@ -360,23 +360,28 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa case( META_GRADIENT_ACTION ): { const MetaGradientAction* pA = (const MetaGradientAction*) pAction; - #ifdef USE_PDFGRADIENTS - m_rOuterFace.DrawGradient( pA->GetRect(), pA->GetGradient() ); - #else - const PolyPolygon aPolyPoly( pA->GetRect() ); - implWriteGradient( aPolyPoly, pA->GetGradient(), pDummyVDev, i_rContext ); - #endif + const Gradient& rGradient = pA->GetGradient(); + if (lcl_canUsePDFAxialShading(rGradient)) + { + m_rOuterFace.DrawGradient( pA->GetRect(), rGradient ); + } + else + { + const PolyPolygon aPolyPoly( pA->GetRect() ); + implWriteGradient( aPolyPoly, rGradient, pDummyVDev, i_rContext ); + } } break; case( META_GRADIENTEX_ACTION ): { const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction; - #ifdef USE_PDFGRADIENTS - m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), pA->GetGradient() ); - #else - implWriteGradient( pA->GetPolyPolygon(), pA->GetGradient(), pDummyVDev, i_rContext ); - #endif + const Gradient& rGradient = pA->GetGradient(); + + if (lcl_canUsePDFAxialShading(rGradient)) + m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), rGradient ); + else + implWriteGradient( pA->GetPolyPolygon(), rGradient, pDummyVDev, i_rContext ); } break; @@ -535,11 +540,14 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa if( pGradAction ) { - #ifdef USE_PDFGRADIENTS - m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() ); - #else - implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext ); - #endif + if (lcl_canUsePDFAxialShading(pGradAction->GetGradient())) + { + m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() ); + } + else + { + implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext ); + } } } else @@ -2038,4 +2046,22 @@ void PDFWriterImpl::writeG4Stream( BitmapReadAccess* i_pBitmap ) rtl_freeMemory( pFirstRefLine ); } +static bool lcl_canUsePDFAxialShading(const Gradient& rGradient) { + switch (rGradient.GetStyle()) + { + case GradientStyle::GradientStyle_LINEAR: + case GradientStyle::GradientStyle_AXIAL: + break; + default: + return false; + } + + // TODO: handle step count + if (rGradient.GetSteps() > 0) + return false; + + return true; +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit