summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorPierre-Eric Pelloux-Prayer <pierre-eric@lanedo.com>2013-09-03 13:31:51 +0200
committerMichael Meeks <michael.meeks@collabora.com>2013-09-09 19:28:01 +0000
commit0f5368434ef506aadfbd44613b7b98270e6a00c7 (patch)
tree6dfb034c60ab9f84bffaf0e61615e92c272b0309 /vcl
parent7323bc340501c2600944193df54295c28de5482c (diff)
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 <michael.meeks@collabora.com> Tested-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/gdi/pdfwriter.cxx13
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx153
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx62
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"
- "<</FunctionType 0\n"
- "/Domain[ 0 1 0 1 ]\n"
- "/Size[ " );
- aLine.append( (sal_Int32)aSize.Width() );
- aLine.append( ' ' );
- aLine.append( (sal_Int32)aSize.Height() );
+ "<</FunctionType 0\n");
+ switch (rObject.m_aGradient.GetStyle())
+ {
+ case GradientStyle::GradientStyle_LINEAR:
+ case GradientStyle::GradientStyle_AXIAL:
+ aLine.append("/Domain[ 0 1]\n");
+ break;
+ default:
+ aLine.append("/Domain[ 0 1 0 1]\n");
+ }
+ aLine.append("/Size[ " );
+ switch (rObject.m_aGradient.GetStyle())
+ {
+ case GradientStyle::GradientStyle_LINEAR:
+ aLine.append('2');
+ break;
+ case GradientStyle::GradientStyle_AXIAL:
+ aLine.append('3');
+ break;
+ default:
+ aLine.append( (sal_Int32)aSize.Width() );
+ aLine.append( ' ' );
+ aLine.append( (sal_Int32)aSize.Height() );
+ }
aLine.append( " ]\n"
"/BitsPerSample 8\n"
"/Range[ 0 1 0 1 0 1 ]\n"
@@ -9505,17 +9529,39 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
checkAndEnableStreamEncryption( nFunctionObject );
beginCompression();
- for( int y = aSize.Height()-1; y >= 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"
- "<</ShadingType 1\n"
- "/ColorSpace/DeviceRGB\n"
- "/AntiAlias true\n"
- "/Domain[ 0 1 0 1 ]\n"
- "/Matrix[ " );
- aLine.append( (sal_Int32)aSize.Width() );
- aLine.append( " 0 0 " );
- aLine.append( (sal_Int32)aSize.Height() );
- aLine.append( " 0 0 ]\n"
- "/Function " );
+ aLine.append( " 0 obj\n");
+ switch (rObject.m_aGradient.GetStyle())
+ {
+ case GradientStyle::GradientStyle_LINEAR:
+ case GradientStyle::GradientStyle_AXIAL:
+ aLine.append("<</ShadingType 2\n");
+ break;
+ default:
+ aLine.append("<</ShadingType 1\n");
+ }
+ aLine.append("/ColorSpace/DeviceRGB\n"
+ "/AntiAlias true\n");
+
+ // Determination of shading axis
+ // See: OutputDevice::ImplDrawLinearGradient for reference
+ Rectangle aRect;
+ aRect.Left() = aRect.Top() = 0;
+ aRect.Right() = aSize.Width();
+ aRect.Bottom() = aSize.Height();
+
+ Rectangle aBoundRect;
+ Point aCenter;
+ sal_uInt16 nAngle = rObject.m_aGradient.GetAngle() % 3600;
+ rObject.m_aGradient.GetBoundRect( aRect, aBoundRect, aCenter );
+
+ const bool bLinear = (rObject.m_aGradient.GetStyle() == GradientStyle_LINEAR);
+ double fBorder = aBoundRect.GetHeight() * rObject.m_aGradient.GetBorder() / 100.0;
+ if ( !bLinear )
+ {
+ fBorder /= 2.0;
+ }
+
+ aBoundRect.Bottom() -= fBorder;
+ if (!bLinear)
+ {
+ aBoundRect.Top() += fBorder;
+ }
+
+ switch (rObject.m_aGradient.GetStyle())
+ {
+ case GradientStyle::GradientStyle_LINEAR:
+ case GradientStyle::GradientStyle_AXIAL:
+ {
+ aLine.append("/Domain[ 0 1 ]\n"
+ "/Coords[ " );
+ Polygon aPoly( 2 );
+ aPoly[0] = aBoundRect.BottomCenter();
+ aPoly[1] = aBoundRect.TopCenter();
+ aPoly.Rotate( aCenter, 3600 - nAngle );
+
+ aLine.append( (sal_Int32) aPoly[0].X() );
+ aLine.append( " " );
+ aLine.append( (sal_Int32) aPoly[0].Y() );
+ aLine.append( " " );
+ aLine.append( (sal_Int32) aPoly[1].X());
+ aLine.append( " ");
+ aLine.append( (sal_Int32) aPoly[1].Y());
+ aLine.append( " ]\n");
+ aLine.append("/Extend [true true]\n");
+ break;
+ }
+ default:
+ aLine.append("/Domain[ 0 1 0 1 ]\n"
+ "/Matrix[ " );
+ aLine.append( (sal_Int32)aSize.Width() );
+ aLine.append( " 0 0 " );
+ aLine.append( (sal_Int32)aSize.Height() );
+ aLine.append( " 0 0 ]\n");
+ }
+ aLine.append("/Function " );
aLine.append( nFunctionObject );
aLine.append( " 0 R\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 <rtl/digest.h>
-#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: */