summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--padmin/source/prtsetup.cxx39
-rw-r--r--padmin/source/prtsetup.hxx3
-rw-r--r--padmin/source/rtsetup.hrc10
-rw-r--r--padmin/source/rtsetup.src14
-rw-r--r--vcl/aqua/source/app/salinst.cxx1
-rw-r--r--vcl/aqua/source/gdi/salprn.cxx2
-rw-r--r--vcl/inc/vcl/jobdata.hxx2
-rw-r--r--vcl/inc/vcl/pdfwriter.hxx21
-rw-r--r--vcl/inc/vcl/print.hxx14
-rw-r--r--vcl/inc/vcl/prntypes.hxx1
-rw-r--r--vcl/inc/vcl/svdata.hxx1
-rw-r--r--[-rwxr-xr-x]vcl/source/gdi/makefile.mk1
-rw-r--r--vcl/source/gdi/pdfwriter.cxx7
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx5
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx10
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx1036
-rw-r--r--vcl/source/gdi/print3.cxx7
-rw-r--r--vcl/source/window/printdlg.cxx1
-rw-r--r--vcl/unx/inc/salprn.h6
-rw-r--r--vcl/unx/source/gdi/salprnpsp.cxx205
-rw-r--r--vcl/unx/source/printer/cupsmgr.cxx14
-rw-r--r--vcl/unx/source/printer/jobdata.cxx13
-rw-r--r--vcl/unx/source/printer/printerinfomanager.cxx12
-rw-r--r--vcl/unx/source/printergfx/printerjob.cxx3
24 files changed, 1382 insertions, 46 deletions
diff --git a/padmin/source/prtsetup.cxx b/padmin/source/prtsetup.cxx
index 17d28515e540..8165b8015403 100644
--- a/padmin/source/prtsetup.cxx
+++ b/padmin/source/prtsetup.cxx
@@ -198,6 +198,7 @@ IMPL_LINK( RTSDialog, ClickButton, Button*, pButton )
m_aJobData.m_nColorDepth = m_pDevicePage->getDepth();
m_aJobData.m_nColorDevice = m_pDevicePage->getColorDevice();
m_aJobData.m_nPSLevel = m_pDevicePage->getLevel();
+ m_aJobData.m_nPDFDevice = m_pDevicePage->getPDFDevice();
}
if( m_pOtherPage )
// write other settings
@@ -363,8 +364,8 @@ RTSDevicePage::RTSDevicePage( RTSDialog* pParent ) :
m_aPPDKeyBox( this, PaResId( RID_RTS_DEVICE_PPDKEY_BOX ) ),
m_aPPDValueText( this, PaResId( RID_RTS_DEVICE_PPDVALUE_TXT ) ),
m_aPPDValueBox( this, PaResId( RID_RTS_DEVICE_PPDVALUE_BOX ) ),
- m_aLevelText( this, PaResId( RID_RTS_DEVICE_LEVEL_TXT ) ),
- m_aLevelBox( this, PaResId( RID_RTS_DEVICE_LEVEL_BOX ) ),
+ m_aLevelText( this, PaResId( RID_RTS_DEVICE_PRINTLANG_TXT ) ),
+ m_aLevelBox( this, PaResId( RID_RTS_DEVICE_PRINTLANG_BOX ) ),
m_aSpaceText( this, PaResId( RID_RTS_DEVICE_SPACE_TXT ) ),
m_aSpaceBox( this, PaResId( RID_RTS_DEVICE_SPACE_BOX ) ),
m_aDepthText( this, PaResId( RID_RTS_DEVICE_DEPTH_TXT ) ),
@@ -385,13 +386,19 @@ RTSDevicePage::RTSDevicePage( RTSDialog* pParent ) :
case 1: m_aSpaceBox.SelectEntry( m_aSpaceColor );break;
}
- m_aLevelBox.InsertEntry( m_pParent->m_aFromDriverString );
- m_aLevelBox.InsertEntry( String( RTL_CONSTASCII_USTRINGPARAM( "1" ) ) );
- m_aLevelBox.InsertEntry( String( RTL_CONSTASCII_USTRINGPARAM( "2" ) ) );
- if( m_pParent->m_aJobData.m_nPSLevel == 0 )
- m_aLevelBox.SelectEntry( m_pParent->m_aFromDriverString );
+ ULONG nLevelEntryData = 0;
+ if( m_pParent->m_aJobData.m_nPDFDevice > 0 )
+ nLevelEntryData = 10;
else
- m_aLevelBox.SelectEntry( String::CreateFromInt32( m_pParent->m_aJobData.m_nPSLevel ) );
+ nLevelEntryData = m_pParent->m_aJobData.m_nPSLevel+1;
+ for( USHORT i = 0; i < m_aLevelBox.GetEntryCount(); i++ )
+ {
+ if( (ULONG)m_aLevelBox.GetEntryData( i ) == nLevelEntryData )
+ {
+ m_aLevelBox.SelectEntryPos( i );
+ break;
+ }
+ }
m_aDepthBox.SelectEntry( String::CreateFromInt32( m_pParent->m_aJobData.m_nColorDepth ).AppendAscii( " Bit" ) );
@@ -430,6 +437,22 @@ void RTSDevicePage::update()
// ------------------------------------------------------------------
+ULONG RTSDevicePage::getLevel()
+{
+ ULONG nLevel = (ULONG)m_aLevelBox.GetEntryData( m_aLevelBox.GetSelectEntryPos() );
+ return nLevel < 10 ? nLevel-1 : 0;
+}
+
+// ------------------------------------------------------------------
+
+ULONG RTSDevicePage::getPDFDevice()
+{
+ ULONG nLevel = (ULONG)m_aLevelBox.GetEntryData( m_aLevelBox.GetSelectEntryPos() );
+ return nLevel > 9 ? 1 : 0;
+}
+
+// ------------------------------------------------------------------
+
IMPL_LINK( RTSDevicePage, SelectHdl, ListBox*, pBox )
{
if( pBox == &m_aPPDKeyBox )
diff --git a/padmin/source/prtsetup.hxx b/padmin/source/prtsetup.hxx
index 65288f738482..72e3d81ee8d7 100644
--- a/padmin/source/prtsetup.hxx
+++ b/padmin/source/prtsetup.hxx
@@ -147,7 +147,8 @@ public:
void update();
- ULONG getLevel() { return m_aLevelBox.GetSelectEntry().ToInt32(); }
+ ULONG getLevel();
+ ULONG getPDFDevice();
ULONG getDepth() { return m_aDepthBox.GetSelectEntry().ToInt32(); }
ULONG getColorDevice()
{
diff --git a/padmin/source/rtsetup.hrc b/padmin/source/rtsetup.hrc
index 30439088de8e..7b6677de7ec4 100644
--- a/padmin/source/rtsetup.hrc
+++ b/padmin/source/rtsetup.hrc
@@ -48,13 +48,13 @@
#define RID_RTS_DEVICEPAGE 4003
#define RID_RTS_DEVICE_COLOR_TXT 1
-#define RID_RTS_DEVICE_GRAY_TXT 2
+#define RID_RTS_DEVICE_GRAY_TXT 2
#define RID_RTS_DEVICE_PPDKEY_TXT 3
#define RID_RTS_DEVICE_PPDKEY_BOX 4
-#define RID_RTS_DEVICE_PPDVALUE_TXT 5
-#define RID_RTS_DEVICE_PPDVALUE_BOX 6
-#define RID_RTS_DEVICE_LEVEL_TXT 7
-#define RID_RTS_DEVICE_LEVEL_BOX 8
+#define RID_RTS_DEVICE_PPDVALUE_TXT 5
+#define RID_RTS_DEVICE_PPDVALUE_BOX 6
+#define RID_RTS_DEVICE_PRINTLANG_TXT 7
+#define RID_RTS_DEVICE_PRINTLANG_BOX 8
#define RID_RTS_DEVICE_SPACE_TXT 9
#define RID_RTS_DEVICE_SPACE_BOX 10
#define RID_RTS_DEVICE_DEPTH_TXT 11
diff --git a/padmin/source/rtsetup.src b/padmin/source/rtsetup.src
index e04374a72245..e2e9a4c8aea3 100644
--- a/padmin/source/rtsetup.src
+++ b/padmin/source/rtsetup.src
@@ -173,17 +173,25 @@ TabPage RID_RTS_DEVICEPAGE
Size = MAP_APPFONT( 105, 111 );
};
- FixedText RID_RTS_DEVICE_LEVEL_TXT
+ FixedText RID_RTS_DEVICE_PRINTLANG_TXT
{
Pos = MAP_APPFONT( 5, 130 );
Size = MAP_APPFONT( 80, 8 );
- Text [ en-US ] = "PostScript ~Level";
+ Text [ en-US ] = "Printer ~Language type";
};
- ListBox RID_RTS_DEVICE_LEVEL_BOX
+ ListBox RID_RTS_DEVICE_PRINTLANG_BOX
{
DropDown = TRUE;
Pos = MAP_APPFONT( 120, 130 );
Size = MAP_APPFONT( 105, 200 );
+ StringList [en-US] =
+ {
+ < "PostScript (Level from driver)" ; 1; > ;
+ < "PostScript Level 1" ; 2; > ;
+ < "PostScript Level 2"; 3; > ;
+ < "PostScript Level 3"; 3; > ;
+ < "PDF"; 10; > ;
+ };
};
FixedText RID_RTS_DEVICE_SPACE_TXT
{
diff --git a/vcl/aqua/source/app/salinst.cxx b/vcl/aqua/source/app/salinst.cxx
index a90488b98b46..f2f21cfbcb6f 100644
--- a/vcl/aqua/source/app/salinst.cxx
+++ b/vcl/aqua/source/app/salinst.cxx
@@ -450,7 +450,6 @@ SalInstance* CreateSalInstance()
ImplGetSVData()->maNWFData.mbProgressNeedsErase = true;
ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase = true;
ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset = 10;
- ImplGetSVData()->maGDIData.mbPrinterPullModel = true;
ImplGetSVData()->maGDIData.mbNoXORClipping = true;
ImplGetSVData()->maWinData.mbNoSaveBackground = true;
diff --git a/vcl/aqua/source/gdi/salprn.cxx b/vcl/aqua/source/gdi/salprn.cxx
index 1c0401f769b5..731fbbb27d37 100644
--- a/vcl/aqua/source/gdi/salprn.cxx
+++ b/vcl/aqua/source/gdi/salprn.cxx
@@ -460,6 +460,8 @@ ULONG AquaSalInfoPrinter::GetCapabilities( const ImplJobSetup* i_pSetupData, USH
return getUseNativeDialog() ? 1 : 0;
case PRINTER_CAPABILITIES_PDF:
return 1;
+ case PRINTER_CAPABILITIES_USEPULLMODEL:
+ return 1;
default: break;
};
return 0;
diff --git a/vcl/inc/vcl/jobdata.hxx b/vcl/inc/vcl/jobdata.hxx
index f576b816dab0..6dc756fe1b5c 100644
--- a/vcl/inc/vcl/jobdata.hxx
+++ b/vcl/inc/vcl/jobdata.hxx
@@ -50,6 +50,7 @@ struct JobData
int m_nColorDepth;
int m_nPSLevel; // 0: no override, else languaglevel to use
int m_nColorDevice; // 0: no override, -1 grey scale, +1 color
+ int m_nPDFDevice; // 0: PostScript, 1: PDF
orientation::type m_eOrientation;
::rtl::OUString m_aPrinterName;
const PPDParser* m_pParser;
@@ -64,6 +65,7 @@ struct JobData
m_nColorDepth( 24 ),
m_nPSLevel( 0 ),
m_nColorDevice( 0 ),
+ m_nPDFDevice( 0 ),
m_eOrientation( orientation::Portrait ),
m_pParser( NULL ) {}
diff --git a/vcl/inc/vcl/pdfwriter.hxx b/vcl/inc/vcl/pdfwriter.hxx
index 419814e5ce97..257f36a0bd24 100644
--- a/vcl/inc/vcl/pdfwriter.hxx
+++ b/vcl/inc/vcl/pdfwriter.hxx
@@ -47,6 +47,7 @@
class Font;
class Point;
class OutputDevice;
+class GDIMetaFile;
class MapMode;
class Polygon;
class LineInfo;
@@ -61,6 +62,8 @@ class Wallpaper;
namespace vcl
{
+class PDFExtOutDevData;
+
struct PDFDocInfo
{
String Title; // document title
@@ -635,6 +638,24 @@ The following structure describes the permissions used in PDF security
returns the page id of the new page
*/
sal_Int32 NewPage( sal_Int32 nPageWidth = 0, sal_Int32 nPageHeight = 0, Orientation eOrientation = Inherit );
+ /** Play a metafile like an outputdevice would do
+ */
+ struct PlayMetafileContext
+ {
+ int m_nMaxImageResolution;
+ bool m_bOnlyLosslessCompression;
+ int m_nJPEGQuality;
+ bool m_bTransparenciesWereRemoved;
+
+ PlayMetafileContext()
+ : m_nMaxImageResolution( 0 )
+ , m_bOnlyLosslessCompression( false )
+ , m_nJPEGQuality( 90 )
+ , m_bTransparenciesWereRemoved( false )
+ {}
+
+ };
+ void PlayMetafile( const GDIMetaFile&, const PlayMetafileContext&, vcl::PDFExtOutDevData* pDevDat = NULL );
/*
* set document info; due to the use of document information in building the PDF document ID, must be called before
diff --git a/vcl/inc/vcl/print.hxx b/vcl/inc/vcl/print.hxx
index af83b2db40e1..071c5a9a9d80 100644
--- a/vcl/inc/vcl/print.hxx
+++ b/vcl/inc/vcl/print.hxx
@@ -514,20 +514,24 @@ public:
bool isDirectPrint() const;
// implementation details, not usable outside vcl
- SAL_DLLPRIVATE int getFilteredPageCount();
+ // don't use outside vcl. Some of these ar exported for
+ // the benefit of vcl's plugins.
+ // Still: DO NOT USE OUTSIDE VCL
+ int getFilteredPageCount();
SAL_DLLPRIVATE PageSize getPageFile( int i_inUnfilteredPage, GDIMetaFile& rMtf, bool i_bMayUseCache = false );
- SAL_DLLPRIVATE PageSize getFilteredPageFile( int i_nFilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache = false );
+ PageSize getFilteredPageFile( int i_nFilteredPage, GDIMetaFile& o_rMtf, bool i_bMayUseCache = false );
SAL_DLLPRIVATE void printFilteredPage( int i_nPage );
SAL_DLLPRIVATE void setPrinter( const boost::shared_ptr<Printer>& );
SAL_DLLPRIVATE void setOptionChangeHdl( const Link& );
- SAL_DLLPRIVATE void createProgressDialog();
+ void createProgressDialog();
+ bool isProgressCanceled();
SAL_DLLPRIVATE void setMultipage( const MultiPageSetup& );
SAL_DLLPRIVATE const MultiPageSetup& getMultipage() const;
- SAL_DLLPRIVATE void setLastPage( sal_Bool i_bLastPage );
+ void setLastPage( sal_Bool i_bLastPage );
SAL_DLLPRIVATE void setReversePrint( sal_Bool i_bReverse );
SAL_DLLPRIVATE bool getReversePrint() const;
SAL_DLLPRIVATE void pushPropertiesToPrinter();
- SAL_DLLPRIVATE void setJobState( com::sun::star::view::PrintableState );
+ void setJobState( com::sun::star::view::PrintableState );
SAL_DLLPRIVATE bool setupPrinter( Window* i_pDlgParent );
SAL_DLLPRIVATE int getPageCountProtected() const;
diff --git a/vcl/inc/vcl/prntypes.hxx b/vcl/inc/vcl/prntypes.hxx
index 6b2af991f2dd..244154360f3b 100644
--- a/vcl/inc/vcl/prntypes.hxx
+++ b/vcl/inc/vcl/prntypes.hxx
@@ -91,5 +91,6 @@ enum Orientation { ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE };
#define PRINTER_CAPABILITIES_PDF ((USHORT)9)
#define PRINTER_CAPABILITIES_EXTERNALDIALOG ((USHORT)10)
#define PRINTER_CAPABILITIES_SETDUPLEX ((USHORT)11)
+#define PRINTER_CAPABILITIES_USEPULLMODEL ((USHORT)12)
#endif // _SV_PRNTYPES_HXX
diff --git a/vcl/inc/vcl/svdata.hxx b/vcl/inc/vcl/svdata.hxx
index fe69b0c0b4d4..0d54a82a1937 100644
--- a/vcl/inc/vcl/svdata.hxx
+++ b/vcl/inc/vcl/svdata.hxx
@@ -208,7 +208,6 @@ struct ImplSVGDIData
BOOL mbFontSubChanged; // TRUE: FontSubstitution wurde zwischen Begin/End geaendert
utl::DefaultFontConfiguration* mpDefaultFontConfiguration;
utl::FontSubstConfiguration* mpFontSubstConfiguration;
- bool mbPrinterPullModel; // true: use pull model instead of normal push model when printing
bool mbNativeFontConfig; // true: do not override UI font
bool mbNoXORClipping; // true: do not use XOR to achieve clipping effects
};
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
index 77df20976c73..ac2e586a41cb 100755..100644
--- a/vcl/source/gdi/makefile.mk
+++ b/vcl/source/gdi/makefile.mk
@@ -63,6 +63,7 @@ EXCEPTIONSFILES= $(SLO)$/salmisc.obj \
$(SLO)$/impgraph.obj \
$(SLO)$/metric.obj \
$(SLO)$/pdfwriter_impl.obj \
+ $(SLO)$/pdfwriter_impl2.obj \
$(SLO)$/pdffontcache.obj\
$(SLO)$/bmpconv.obj \
$(SLO)$/pdfextoutdevdata.obj \
diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx
index 5dcce25a0315..969bc51b3cac 100644
--- a/vcl/source/gdi/pdfwriter.cxx
+++ b/vcl/source/gdi/pdfwriter.cxx
@@ -40,7 +40,7 @@ PDFWriter::AnyWidget::~AnyWidget()
PDFWriter::PDFWriter( const PDFWriter::PDFWriterContext& rContext )
:
- pImplementation( new PDFWriterImpl( rContext ) )
+ pImplementation( new PDFWriterImpl( rContext, *this ) )
{
}
@@ -569,3 +569,8 @@ std::set< PDFWriter::ErrorCode > PDFWriter::GetErrors()
{
return ((PDFWriterImpl*)pImplementation)->getErrors();
}
+
+void PDFWriter::PlayMetafile( const GDIMetaFile& i_rMTF, const vcl::PDFWriter::PlayMetafileContext& i_rPlayContext, PDFExtOutDevData* i_pData )
+{
+ ((PDFWriterImpl*)pImplementation)->playMetafile( i_rMTF, i_pData, i_rPlayContext, NULL);
+}
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 7b7f3bbcb4d3..0a8004474c58 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -1692,7 +1692,7 @@ void PDFWriterImpl::PDFPage::appendWaveLine( sal_Int32 nWidth, sal_Int32 nY, sal
* class PDFWriterImpl
*/
-PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext )
+PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWriter& i_rOuterFace )
:
m_pReferenceDevice( NULL ),
m_aMapMode( MAP_POINT, Point(), Fraction( 1L, pointToPixel(1) ), Fraction( 1L, pointToPixel(1) ) ),
@@ -1718,7 +1718,8 @@ PDFWriterImpl::PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext )
m_aCreationMetaDateString( 64 ),
m_pEncryptionBuffer( NULL ),
m_nEncryptionBufferSize( 0 ),
- m_bIsPDF_A1( false )
+ m_bIsPDF_A1( false ),
+ m_rOuterFace( i_rOuterFace )
{
#ifdef DO_TEST_PDF
static bool bOnce = true;
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 2eacdc215dd8..9457aea5f0c2 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -1095,6 +1095,7 @@ i12626
/* true if PDF/A-1a or PDF/A-1b is output */
sal_Bool m_bIsPDF_A1;
+ PDFWriter& m_rOuterFace;
/*
i12626
@@ -1109,8 +1110,14 @@ methods for PDF security
/* algorithm 3.4 or 3.5: computing the encryption dictionary's user password value ( /U ) revision 2 or 3 of the standard security handler */
void computeUDictionaryValue();
+ // helper for playMetafile
+ void implWriteGradient( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
+ VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
+ void implWriteBitmapEx( const Point& rPoint, const Size& rSize, const BitmapEx& rBitmapEx,
+ VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
+
public:
- PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext );
+ PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, PDFWriter& );
~PDFWriterImpl();
/* for OutputDevice so the reference device can have a list
@@ -1134,6 +1141,7 @@ public:
bool emit();
std::set< PDFWriter::ErrorCode > getErrors();
void insertError( PDFWriter::ErrorCode eErr ) { m_aErrors.insert( eErr ); }
+ void playMetafile( const GDIMetaFile&, vcl::PDFExtOutDevData*, const vcl::PDFWriter::PlayMetafileContext&, VirtualDevice* pDummyDev = NULL );
Size getCurPageSize() const
{
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
new file mode 100644
index 000000000000..3d1d55320922
--- /dev/null
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -0,0 +1,1036 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_vcl.hxx"
+
+#include "pdfwriter_impl.hxx"
+#include "vcl/pdfextoutdevdata.hxx"
+#include "vcl/virdev.hxx"
+#include "vcl/gdimtf.hxx"
+#include "vcl/metaact.hxx"
+#include "vcl/graph.hxx"
+#include "vcl/svdata.hxx"
+#include "unotools/streamwrap.hxx"
+#include "unotools/processfactory.hxx"
+
+#include "comphelper/processfactory.hxx"
+#include "com/sun/star/beans/PropertyValue.hpp"
+#include "com/sun/star/io/XSeekable.hpp"
+#include "com/sun/star/graphic/XGraphicProvider.hpp"
+
+using namespace vcl;
+using namespace rtl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+
+// -----------------------------------------------------------------------------
+
+void PDFWriterImpl::implWriteGradient( const PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient,
+ VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
+{
+ GDIMetaFile aTmpMtf;
+
+ i_pDummyVDev->AddGradientActions( i_rPolyPoly.GetBoundRect(), i_rGradient, aTmpMtf );
+
+ m_rOuterFace.Push();
+ m_rOuterFace.IntersectClipRegion( i_rPolyPoly.getB2DPolyPolygon() );
+ playMetafile( aTmpMtf, NULL, i_rContext, i_pDummyVDev );
+ m_rOuterFace.Pop();
+}
+
+// -----------------------------------------------------------------------------
+
+void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSize, const BitmapEx& i_rBitmapEx,
+ VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
+{
+ if ( !i_rBitmapEx.IsEmpty() && i_rSize.Width() && i_rSize.Height() )
+ {
+ BitmapEx aBitmapEx( i_rBitmapEx );
+ Point aPoint( i_rPoint );
+ Size aSize( i_rSize );
+
+ // #i19065# Negative sizes have mirror semantics on
+ // OutputDevice. BitmapEx and co. have no idea about that, so
+ // perform that _before_ doing anything with aBitmapEx.
+ ULONG nMirrorFlags(BMP_MIRROR_NONE);
+ if( aSize.Width() < 0 )
+ {
+ aSize.Width() *= -1;
+ aPoint.X() -= aSize.Width();
+ nMirrorFlags |= BMP_MIRROR_HORZ;
+ }
+ if( aSize.Height() < 0 )
+ {
+ aSize.Height() *= -1;
+ aPoint.Y() -= aSize.Height();
+ nMirrorFlags |= BMP_MIRROR_VERT;
+ }
+
+ if( nMirrorFlags != BMP_MIRROR_NONE )
+ {
+ aBitmapEx.Mirror( nMirrorFlags );
+ }
+ if( i_rContext.m_nMaxImageResolution > 50 )
+ {
+ // do downsampling if neccessary
+ const Size aDstSizeTwip( i_pDummyVDev->PixelToLogic( i_pDummyVDev->LogicToPixel( aSize ), MAP_TWIP ) );
+ const Size aBmpSize( aBitmapEx.GetSizePixel() );
+ const double fBmpPixelX = aBmpSize.Width();
+ const double fBmpPixelY = aBmpSize.Height();
+ const double fMaxPixelX = aDstSizeTwip.Width() * i_rContext.m_nMaxImageResolution / 1440.0;
+ const double fMaxPixelY = aDstSizeTwip.Height() * i_rContext.m_nMaxImageResolution / 1440.0;
+
+ // check, if the bitmap DPI exceeds the maximum DPI (allow 4 pixel rounding tolerance)
+ if( ( ( fBmpPixelX > ( fMaxPixelX + 4 ) ) ||
+ ( fBmpPixelY > ( fMaxPixelY + 4 ) ) ) &&
+ ( fBmpPixelY > 0.0 ) && ( fMaxPixelY > 0.0 ) )
+ {
+ // do scaling
+ Size aNewBmpSize;
+ const double fBmpWH = fBmpPixelX / fBmpPixelY;
+ const double fMaxWH = fMaxPixelX / fMaxPixelY;
+
+ if( fBmpWH < fMaxWH )
+ {
+ aNewBmpSize.Width() = FRound( fMaxPixelY * fBmpWH );
+ aNewBmpSize.Height() = FRound( fMaxPixelY );
+ }
+ else if( fBmpWH > 0.0 )
+ {
+ aNewBmpSize.Width() = FRound( fMaxPixelX );
+ aNewBmpSize.Height() = FRound( fMaxPixelX / fBmpWH);
+ }
+ if( aNewBmpSize.Width() && aNewBmpSize.Height() )
+ aBitmapEx.Scale( aNewBmpSize );
+ else
+ aBitmapEx.SetEmpty();
+ }
+ }
+
+ const Size aSizePixel( aBitmapEx.GetSizePixel() );
+ if ( aSizePixel.Width() && aSizePixel.Height() )
+ {
+ sal_Bool bUseJPGCompression = !i_rContext.m_bOnlyLosslessCompression;
+ if ( ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
+ bUseJPGCompression = sal_False;
+
+ SvMemoryStream aStrm;
+ Bitmap aMask;
+
+ bool bTrueColorJPG = true;
+ if ( bUseJPGCompression )
+ {
+ sal_uInt32 nZippedFileSize; // sj: we will calculate the filesize of a zipped bitmap
+ { // to determine if jpeg compression is usefull
+ SvMemoryStream aTemp;
+ aTemp.SetCompressMode( aTemp.GetCompressMode() | COMPRESSMODE_ZBITMAP );
+ aTemp.SetVersion( SOFFICE_FILEFORMAT_40 ); // sj: up from version 40 our bitmap stream operator
+ aTemp << aBitmapEx; // is capable of zlib stream compression
+ aTemp.Seek( STREAM_SEEK_TO_END );
+ nZippedFileSize = aTemp.Tell();
+ }
+ if ( aBitmapEx.IsTransparent() )
+ {
+ if ( aBitmapEx.IsAlpha() )
+ aMask = aBitmapEx.GetAlpha().GetBitmap();
+ else
+ aMask = aBitmapEx.GetMask();
+ }
+ Graphic aGraphic( aBitmapEx.GetBitmap() );
+ sal_Int32 nColorMode = 0;
+
+ Sequence< PropertyValue > aFilterData( 2 );
+ aFilterData[ 0 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) );
+ aFilterData[ 0 ].Value <<= sal_Int32(i_rContext.m_nJPEGQuality);
+ aFilterData[ 1 ].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) );
+ aFilterData[ 1 ].Value <<= nColorMode;
+
+ try
+ {
+ uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( aStrm );
+ Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
+ Reference< graphic::XGraphicProvider > xGraphicProvider( ImplGetSVData()->maAppData.mxMSF->createInstance(
+ OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY );
+ if ( xGraphicProvider.is() )
+ {
+ Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
+ Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
+ rtl::OUString aMimeType( ::rtl::OUString::createFromAscii( "image/jpeg" ) );
+ uno::Sequence< beans::PropertyValue > aOutMediaProperties( 3 );
+ aOutMediaProperties[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
+ aOutMediaProperties[0].Value <<= xOut;
+ aOutMediaProperties[1].Name = ::rtl::OUString::createFromAscii( "MimeType" );
+ aOutMediaProperties[1].Value <<= aMimeType;
+ aOutMediaProperties[2].Name = ::rtl::OUString::createFromAscii( "FilterData" );
+ aOutMediaProperties[2].Value <<= aFilterData;
+ xGraphicProvider->storeGraphic( xGraphic, aOutMediaProperties );
+ xOut->flush();
+ if ( xSeekable->getLength() > nZippedFileSize )
+ {
+ bUseJPGCompression = sal_False;
+ }
+ else
+ {
+ aStrm.Seek( STREAM_SEEK_TO_END );
+
+ xSeekable->seek( 0 );
+ Sequence< PropertyValue > aArgs( 1 );
+ aArgs[ 0 ].Name = ::rtl::OUString::createFromAscii( "InputStream" );
+ aArgs[ 0 ].Value <<= xStream;
+ Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
+ if ( xPropSet.is() )
+ {
+ sal_Int16 nBitsPerPixel = 24;
+ if ( xPropSet->getPropertyValue( ::rtl::OUString::createFromAscii( "BitsPerPixel" ) ) >>= nBitsPerPixel )
+ {
+ bTrueColorJPG = nBitsPerPixel != 8;
+ }
+ }
+ }
+ }
+ else
+ bUseJPGCompression = sal_False;
+ }
+ catch( uno::Exception& )
+ {
+ bUseJPGCompression = sal_False;
+ }
+ }
+ if ( bUseJPGCompression )
+ m_rOuterFace.DrawJPGBitmap( aStrm, bTrueColorJPG, aSizePixel, Rectangle( aPoint, aSize ), aMask );
+ else if ( aBitmapEx.IsTransparent() )
+ m_rOuterFace.DrawBitmapEx( aPoint, aSize, aBitmapEx );
+ else
+ m_rOuterFace.DrawBitmap( aPoint, aSize, aBitmapEx.GetBitmap() );
+ }
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+
+void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevData* i_pOutDevData, const vcl::PDFWriter::PlayMetafileContext& i_rContext, VirtualDevice* pDummyVDev )
+{
+ bool bAssertionFired( false );
+
+ VirtualDevice* pPrivateDevice = NULL;
+ if( ! pDummyVDev )
+ {
+ pPrivateDevice = pDummyVDev = new VirtualDevice();
+ pDummyVDev->EnableOutput( sal_False );
+ pDummyVDev->SetMapMode( i_rMtf.GetPrefMapMode() );
+ }
+
+ GDIMetaFile aMtf( i_rMtf );
+
+ for( sal_uInt32 i = 0, nCount = aMtf.GetActionCount(); i < nCount; )
+ {
+ if ( !i_pOutDevData || !i_pOutDevData->PlaySyncPageAct( m_rOuterFace, i ) )
+ {
+ const MetaAction* pAction = aMtf.GetAction( i );
+ const USHORT nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
+ m_rOuterFace.DrawPixel( pA->GetPoint(), pA->GetColor() );
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ const MetaPointAction* pA = (const MetaPointAction*) pAction;
+ m_rOuterFace.DrawPixel( pA->GetPoint() );
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ const MetaLineAction* pA = (const MetaLineAction*) pAction;
+ if ( pA->GetLineInfo().IsDefault() )
+ m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint() );
+ else
+ m_rOuterFace.DrawLine( pA->GetStartPoint(), pA->GetEndPoint(), pA->GetLineInfo() );
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ const MetaRectAction* pA = (const MetaRectAction*) pAction;
+ m_rOuterFace.DrawRect( pA->GetRect() );
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
+ m_rOuterFace.DrawRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
+ m_rOuterFace.DrawEllipse( pA->GetRect() );
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ const MetaArcAction* pA = (const MetaArcAction*) pAction;
+ m_rOuterFace.DrawArc( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ const MetaArcAction* pA = (const MetaArcAction*) pAction;
+ m_rOuterFace.DrawPie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ const MetaChordAction* pA = (const MetaChordAction*) pAction;
+ m_rOuterFace.DrawChord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ const MetaPolygonAction* pA = (const MetaPolygonAction*) pAction;
+ m_rOuterFace.DrawPolygon( pA->GetPolygon() );
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
+ if ( pA->GetLineInfo().IsDefault() )
+ m_rOuterFace.DrawPolyLine( pA->GetPolygon() );
+ else
+ m_rOuterFace.DrawPolyLine( pA->GetPolygon(), pA->GetLineInfo() );
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
+ m_rOuterFace.DrawPolyPolygon( pA->GetPolyPolygon() );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
+ const PolyPolygon aPolyPoly( pA->GetRect() );
+
+ implWriteGradient( aPolyPoly, pA->GetGradient(), pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
+ implWriteGradient( pA->GetPolyPolygon(), pA->GetGradient(), pDummyVDev, i_rContext );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
+ m_rOuterFace.DrawHatch( pA->GetPolyPolygon(), pA->GetHatch() );
+ }
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ {
+ const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
+ m_rOuterFace.DrawTransparent( pA->GetPolyPolygon(), pA->GetTransparence() );
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
+
+ GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
+ const Point& rPos = pA->GetPoint();
+ const Size& rSize= pA->GetSize();
+ const Gradient& rTransparenceGradient = pA->GetGradient();
+
+ // special case constant alpha value
+ if( rTransparenceGradient.GetStartColor() == rTransparenceGradient.GetEndColor() )
+ {
+ const Color aTransCol( rTransparenceGradient.GetStartColor() );
+ const USHORT nTransPercent = aTransCol.GetLuminance() * 100 / 255;
+ m_rOuterFace.BeginTransparencyGroup();
+ playMetafile( aTmpMtf, NULL, i_rContext, pDummyVDev );
+ m_rOuterFace.EndTransparencyGroup( Rectangle( rPos, rSize ), nTransPercent );
+ }
+ else
+ {
+ const Size aDstSizeTwip( pDummyVDev->PixelToLogic( pDummyVDev->LogicToPixel( rSize ), MAP_TWIP ) );
+ sal_Int32 nMaxBmpDPI = i_rContext.m_bOnlyLosslessCompression ? 300 : 72;
+ if( i_rContext.m_nMaxImageResolution > 50 )
+ {
+ if ( nMaxBmpDPI > i_rContext.m_nMaxImageResolution )
+ nMaxBmpDPI = i_rContext.m_nMaxImageResolution;
+ }
+ const sal_Int32 nPixelX = (sal_Int32)((double)aDstSizeTwip.Width() * (double)nMaxBmpDPI / 1440.0);
+ const sal_Int32 nPixelY = (sal_Int32)((double)aDstSizeTwip.Height() * (double)nMaxBmpDPI / 1440.0);
+ if ( nPixelX && nPixelY )
+ {
+ Size aDstSizePixel( nPixelX, nPixelY );
+ VirtualDevice* pVDev = new VirtualDevice;
+ if( pVDev->SetOutputSizePixel( aDstSizePixel ) )
+ {
+ Bitmap aPaint, aMask;
+ AlphaMask aAlpha;
+ Point aPoint;
+
+ MapMode aMapMode( pDummyVDev->GetMapMode() );
+ aMapMode.SetOrigin( aPoint );
+ pVDev->SetMapMode( aMapMode );
+ Size aDstSize( pVDev->PixelToLogic( aDstSizePixel ) );
+
+ Point aMtfOrigin( aTmpMtf.GetPrefMapMode().GetOrigin() );
+ if ( aMtfOrigin.X() || aMtfOrigin.Y() )
+ aTmpMtf.Move( -aMtfOrigin.X(), -aMtfOrigin.Y() );
+ double fScaleX = (double)aDstSize.Width() / (double)aTmpMtf.GetPrefSize().Width();
+ double fScaleY = (double)aDstSize.Height() / (double)aTmpMtf.GetPrefSize().Height();
+ if( fScaleX != 1.0 || fScaleY != 1.0 )
+ aTmpMtf.Scale( fScaleX, fScaleY );
+ aTmpMtf.SetPrefMapMode( aMapMode );
+
+ // create paint bitmap
+ aTmpMtf.WindStart();
+ aTmpMtf.Play( pVDev, aPoint, aDstSize );
+ aTmpMtf.WindStart();
+
+ pVDev->EnableMapMode( FALSE );
+ aPaint = pVDev->GetBitmap( aPoint, aDstSizePixel );
+ pVDev->EnableMapMode( TRUE );
+
+ // create mask bitmap
+ pVDev->SetLineColor( COL_BLACK );
+ pVDev->SetFillColor( COL_BLACK );
+ pVDev->DrawRect( Rectangle( aPoint, aDstSize ) );
+ pVDev->SetDrawMode( DRAWMODE_WHITELINE | DRAWMODE_WHITEFILL | DRAWMODE_WHITETEXT |
+ DRAWMODE_WHITEBITMAP | DRAWMODE_WHITEGRADIENT );
+ aTmpMtf.WindStart();
+ aTmpMtf.Play( pVDev, aPoint, aDstSize );
+ aTmpMtf.WindStart();
+ pVDev->EnableMapMode( FALSE );
+ aMask = pVDev->GetBitmap( aPoint, aDstSizePixel );
+ pVDev->EnableMapMode( TRUE );
+
+ // create alpha mask from gradient
+ pVDev->SetDrawMode( DRAWMODE_GRAYGRADIENT );
+ pVDev->DrawGradient( Rectangle( aPoint, aDstSize ), rTransparenceGradient );
+ pVDev->SetDrawMode( DRAWMODE_DEFAULT );
+ pVDev->EnableMapMode( FALSE );
+ pVDev->DrawMask( aPoint, aDstSizePixel, aMask, Color( COL_WHITE ) );
+ aAlpha = pVDev->GetBitmap( aPoint, aDstSizePixel );
+ implWriteBitmapEx( rPos, rSize, BitmapEx( aPaint, aAlpha ), pDummyVDev, i_rContext );
+ }
+ delete pVDev;
+ }
+ }
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
+ const GDIMetaFile aSubstitute( pA->GetSubstitute() );
+
+ m_rOuterFace.Push();
+ pDummyVDev->Push();
+
+ MapMode aMapMode( aSubstitute.GetPrefMapMode() );
+ Size aOutSize( pDummyVDev->LogicToLogic( pA->GetSize(), pDummyVDev->GetMapMode(), aMapMode ) );
+ aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
+ aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
+ aMapMode.SetOrigin( pDummyVDev->LogicToLogic( pA->GetPoint(), pDummyVDev->GetMapMode(), aMapMode ) );
+
+ m_rOuterFace.SetMapMode( aMapMode );
+ pDummyVDev->SetMapMode( aMapMode );
+ playMetafile( aSubstitute, NULL, i_rContext, pDummyVDev );
+ pDummyVDev->Pop();
+ m_rOuterFace.Pop();
+ }
+ break;
+
+ case( META_COMMENT_ACTION ):
+ if( ! i_rContext.m_bTransparenciesWereRemoved )
+ {
+ const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
+ String aSkipComment;
+
+ if( pA->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_BEGIN" ) == COMPARE_EQUAL )
+ {
+ const MetaGradientExAction* pGradAction = NULL;
+ sal_Bool bDone = sal_False;
+
+ while( !bDone && ( ++i < nCount ) )
+ {
+ pAction = aMtf.GetAction( i );
+
+ if( pAction->GetType() == META_GRADIENTEX_ACTION )
+ pGradAction = (const MetaGradientExAction*) pAction;
+ else if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
+ ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XGRAD_SEQ_END" ) == COMPARE_EQUAL ) )
+ {
+ bDone = sal_True;
+ }
+ }
+
+ if( pGradAction )
+ implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext );
+ }
+ else
+ {
+ const BYTE* pData = pA->GetData();
+ if ( pData )
+ {
+ SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
+ sal_Bool bSkipSequence = sal_False;
+ ByteString sSeqEnd;
+
+ if( pA->GetComment().Equals( "XPATHSTROKE_SEQ_BEGIN" ) )
+ {
+ sSeqEnd = ByteString( "XPATHSTROKE_SEQ_END" );
+ SvtGraphicStroke aStroke;
+ aMemStm >> aStroke;
+
+ Polygon aPath;
+ aStroke.getPath( aPath );
+
+ PolyPolygon aStartArrow;
+ PolyPolygon aEndArrow;
+ double fTransparency( aStroke.getTransparency() );
+ double fStrokeWidth( aStroke.getStrokeWidth() );
+ SvtGraphicStroke::DashArray aDashArray;
+
+ aStroke.getStartArrow( aStartArrow );
+ aStroke.getEndArrow( aEndArrow );
+ aStroke.getDashArray( aDashArray );
+
+ bSkipSequence = sal_True;
+ if ( aStartArrow.Count() || aEndArrow.Count() )
+ bSkipSequence = sal_False;
+ if ( aDashArray.size() && ( fStrokeWidth != 0.0 ) && ( fTransparency == 0.0 ) )
+ bSkipSequence = sal_False;
+ if ( bSkipSequence )
+ {
+ PDFWriter::ExtLineInfo aInfo;
+ aInfo.m_fLineWidth = fStrokeWidth;
+ aInfo.m_fTransparency = fTransparency;
+ aInfo.m_fMiterLimit = aStroke.getMiterLimit();
+ switch( aStroke.getCapType() )
+ {
+ default:
+ case SvtGraphicStroke::capButt: aInfo.m_eCap = PDFWriter::capButt;break;
+ case SvtGraphicStroke::capRound: aInfo.m_eCap = PDFWriter::capRound;break;
+ case SvtGraphicStroke::capSquare: aInfo.m_eCap = PDFWriter::capSquare;break;
+ }
+ switch( aStroke.getJoinType() )
+ {
+ default:
+ case SvtGraphicStroke::joinMiter: aInfo.m_eJoin = PDFWriter::joinMiter;break;
+ case SvtGraphicStroke::joinRound: aInfo.m_eJoin = PDFWriter::joinRound;break;
+ case SvtGraphicStroke::joinBevel: aInfo.m_eJoin = PDFWriter::joinBevel;break;
+ case SvtGraphicStroke::joinNone:
+ aInfo.m_eJoin = PDFWriter::joinMiter;
+ aInfo.m_fMiterLimit = 0.0;
+ break;
+ }
+ aInfo.m_aDashArray = aDashArray;
+
+ if(SvtGraphicStroke::joinNone == aStroke.getJoinType()
+ && fStrokeWidth > 0.0)
+ {
+ // emulate no edge rounding by handling single edges
+ const sal_uInt16 nPoints(aPath.GetSize());
+ const bool bCurve(aPath.HasFlags());
+
+ for(sal_uInt16 a(0); a + 1 < nPoints; a++)
+ {
+ if(bCurve
+ && POLY_NORMAL != aPath.GetFlags(a + 1)
+ && a + 2 < nPoints
+ && POLY_NORMAL != aPath.GetFlags(a + 2)
+ && a + 3 < nPoints)
+ {
+ const Polygon aSnippet(4,
+ aPath.GetConstPointAry() + a,
+ aPath.GetConstFlagAry() + a);
+ m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
+ a += 2;
+ }
+ else
+ {
+ const Polygon aSnippet(2,
+ aPath.GetConstPointAry() + a);
+ m_rOuterFace.DrawPolyLine( aSnippet, aInfo );
+ }
+ }
+ }
+ else
+ {
+ m_rOuterFace.DrawPolyLine( aPath, aInfo );
+ }
+ }
+ }
+ else if ( pA->GetComment().Equals( "XPATHFILL_SEQ_BEGIN" ) )
+ {
+ sSeqEnd = ByteString( "XPATHFILL_SEQ_END" );
+ SvtGraphicFill aFill;
+ aMemStm >> aFill;
+
+ if ( ( aFill.getFillType() == SvtGraphicFill::fillSolid ) && ( aFill.getFillRule() == SvtGraphicFill::fillEvenOdd ) )
+ {
+ double fTransparency = aFill.getTransparency();
+ if ( fTransparency == 0.0 )
+ {
+ PolyPolygon aPath;
+ aFill.getPath( aPath );
+
+ bSkipSequence = sal_True;
+ m_rOuterFace.DrawPolyPolygon( aPath );
+ }
+ else if ( fTransparency == 1.0 )
+ bSkipSequence = sal_True;
+ }
+/* #i81548# removing optimization for fill textures, because most of the texture settings are not
+ exported properly. In OpenOffice 3.1 the drawing layer will support graphic primitives, then it
+ will not be a problem to optimize the filltexture export. But for wysiwyg is more important than
+ filesize.
+ else if( aFill.getFillType() == SvtGraphicFill::fillTexture && aFill.isTiling() )
+ {
+ sal_Int32 nPattern = mnCachePatternId;
+ Graphic aPatternGraphic;
+ aFill.getGraphic( aPatternGraphic );
+ bool bUseCache = false;
+ SvtGraphicFill::Transform aPatTransform;
+ aFill.getTransform( aPatTransform );
+
+ if( mnCachePatternId >= 0 )
+ {
+ SvtGraphicFill::Transform aCacheTransform;
+ maCacheFill.getTransform( aCacheTransform );
+ if( aCacheTransform.matrix[0] == aPatTransform.matrix[0] &&
+ aCacheTransform.matrix[1] == aPatTransform.matrix[1] &&
+ aCacheTransform.matrix[2] == aPatTransform.matrix[2] &&
+ aCacheTransform.matrix[3] == aPatTransform.matrix[3] &&
+ aCacheTransform.matrix[4] == aPatTransform.matrix[4] &&
+ aCacheTransform.matrix[5] == aPatTransform.matrix[5]
+ )
+ {
+ Graphic aCacheGraphic;
+ maCacheFill.getGraphic( aCacheGraphic );
+ if( aCacheGraphic == aPatternGraphic )
+ bUseCache = true;
+ }
+ }
+
+ if( ! bUseCache )
+ {
+
+ // paint graphic to metafile
+ GDIMetaFile aPattern;
+ pDummyVDev->SetConnectMetaFile( &aPattern );
+ pDummyVDev->Push();
+ pDummyVDev->SetMapMode( aPatternGraphic.GetPrefMapMode() );
+
+ aPatternGraphic.Draw( &rDummyVDev, Point( 0, 0 ) );
+ pDummyVDev->Pop();
+ pDummyVDev->SetConnectMetaFile( NULL );
+ aPattern.WindStart();
+
+ MapMode aPatternMapMode( aPatternGraphic.GetPrefMapMode() );
+ // prepare pattern from metafile
+ Size aPrefSize( aPatternGraphic.GetPrefSize() );
+ // FIXME: this magic -1 shouldn't be necessary
+ aPrefSize.Width() -= 1;
+ aPrefSize.Height() -= 1;
+ aPrefSize = m_rOuterFace.GetReferenceDevice()->
+ LogicToLogic( aPrefSize,
+ &aPatternMapMode,
+ &m_rOuterFace.GetReferenceDevice()->GetMapMode() );
+ // build bounding rectangle of pattern
+ Rectangle aBound( Point( 0, 0 ), aPrefSize );
+ m_rOuterFace.BeginPattern( aBound );
+ m_rOuterFace.Push();
+ pDummyVDev->Push();
+ m_rOuterFace.SetMapMode( aPatternMapMode );
+ pDummyVDev->SetMapMode( aPatternMapMode );
+ ImplWriteActions( m_rOuterFace, NULL, aPattern, rDummyVDev );
+ pDummyVDev->Pop();
+ m_rOuterFace.Pop();
+
+ nPattern = m_rOuterFace.EndPattern( aPatTransform );
+
+ // try some caching and reuse pattern
+ mnCachePatternId = nPattern;
+ maCacheFill = aFill;
+ }
+
+ // draw polypolygon with pattern fill
+ PolyPolygon aPath;
+ aFill.getPath( aPath );
+ m_rOuterFace.DrawPolyPolygon( aPath, nPattern, aFill.getFillRule() == SvtGraphicFill::fillEvenOdd );
+
+ bSkipSequence = sal_True;
+ }
+*/
+ }
+ if ( bSkipSequence )
+ {
+ while( ++i < nCount )
+ {
+ pAction = aMtf.GetAction( i );
+ if ( pAction->GetType() == META_COMMENT_ACTION )
+ {
+ ByteString sComment( ((MetaCommentAction*)pAction)->GetComment() );
+ if ( sComment.Equals( sSeqEnd ) )
+ break;
+ }
+ // #i44496#
+ // the replacement action for stroke is a filled rectangle
+ // the set fillcolor of the replacement is part of the graphics
+ // state and must not be skipped
+ else if( pAction->GetType() == META_FILLCOLOR_ACTION )
+ {
+ const MetaFillColorAction* pMA = (const MetaFillColorAction*) pAction;
+ if( pMA->IsSetting() )
+ m_rOuterFace.SetFillColor( pMA->GetColor() );
+ else
+ m_rOuterFace.SetFillColor();
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
+ BitmapEx aBitmapEx( pA->GetBitmap() );
+ Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
+ aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
+ if( ! ( aSize.Width() && aSize.Height() ) )
+ aSize = pDummyVDev->PixelToLogic( aBitmapEx.GetSizePixel() );
+ implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+ implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), BitmapEx( pA->GetBitmap() ), pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
+ BitmapEx aBitmapEx( pA->GetBitmap() );
+ aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
+ implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
+ BitmapEx aBitmapEx( pA->GetBitmapEx() );
+ Size aSize( OutputDevice::LogicToLogic( aBitmapEx.GetPrefSize(),
+ aBitmapEx.GetPrefMapMode(), pDummyVDev->GetMapMode() ) );
+ implWriteBitmapEx( pA->GetPoint(), aSize, aBitmapEx, pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), pA->GetBitmapEx(), pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
+ BitmapEx aBitmapEx( pA->GetBitmapEx() );
+ aBitmapEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
+ implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), aBitmapEx, pDummyVDev, i_rContext );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ case( META_MASKSCALE_ACTION ):
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ DBG_ERROR( "MetaMask...Action not supported yet" );
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ const MetaTextAction* pA = (const MetaTextAction*) pAction;
+ m_rOuterFace.DrawText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ) );
+ }
+ break;
+
+ case( META_TEXTRECT_ACTION ):
+ {
+ const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
+ m_rOuterFace.DrawText( pA->GetRect(), String( pA->GetText() ), pA->GetStyle() );
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
+ m_rOuterFace.DrawTextArray( pA->GetPoint(), pA->GetText(), pA->GetDXArray(), pA->GetIndex(), pA->GetLen() );
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ {
+ const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
+ m_rOuterFace.DrawStretchText( pA->GetPoint(), pA->GetWidth(), pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ }
+ break;
+
+
+ case( META_TEXTLINE_ACTION ):
+ {
+ const MetaTextLineAction* pA = (const MetaTextLineAction*) pAction;
+ m_rOuterFace.DrawTextLine( pA->GetStartPoint(), pA->GetWidth(), pA->GetStrikeout(), pA->GetUnderline(), pA->GetOverline() );
+
+ }
+ break;
+
+ case( META_CLIPREGION_ACTION ):
+ {
+ const MetaClipRegionAction* pA = (const MetaClipRegionAction*) pAction;
+
+ if( pA->IsClipping() )
+ {
+ if( pA->GetRegion().IsEmpty() )
+ m_rOuterFace.SetClipRegion( basegfx::B2DPolyPolygon() );
+ else
+ {
+ Region aReg( pA->GetRegion() );
+ m_rOuterFace.SetClipRegion( aReg.ConvertToB2DPolyPolygon() );
+ }
+ }
+ else
+ m_rOuterFace.SetClipRegion();
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
+ m_rOuterFace.IntersectClipRegion( pA->GetRect() );
+ }
+ break;
+
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ {
+ const MetaISectRegionClipRegionAction* pA = (const MetaISectRegionClipRegionAction*) pAction;
+ Region aReg( pA->GetRegion() );
+ m_rOuterFace.IntersectClipRegion( aReg.ConvertToB2DPolyPolygon() );
+ }
+ break;
+
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*) pAction;
+ m_rOuterFace.MoveClipRegion( pA->GetHorzMove(), pA->GetVertMove() );
+ }
+ break;
+
+ case( META_MAPMODE_ACTION ):
+ {
+ const_cast< MetaAction* >( pAction )->Execute( pDummyVDev );
+ m_rOuterFace.SetMapMode( pDummyVDev->GetMapMode() );
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ const MetaLineColorAction* pA = (const MetaLineColorAction*) pAction;
+
+ if( pA->IsSetting() )
+ m_rOuterFace.SetLineColor( pA->GetColor() );
+ else
+ m_rOuterFace.SetLineColor();
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ const MetaFillColorAction* pA = (const MetaFillColorAction*) pAction;
+
+ if( pA->IsSetting() )
+ m_rOuterFace.SetFillColor( pA->GetColor() );
+ else
+ m_rOuterFace.SetFillColor();
+ }
+ break;
+
+ case( META_TEXTLINECOLOR_ACTION ):
+ {
+ const MetaTextLineColorAction* pA = (const MetaTextLineColorAction*) pAction;
+
+ if( pA->IsSetting() )
+ m_rOuterFace.SetTextLineColor( pA->GetColor() );
+ else
+ m_rOuterFace.SetTextLineColor();
+ }
+ break;
+
+ case( META_OVERLINECOLOR_ACTION ):
+ {
+ const MetaOverlineColorAction* pA = (const MetaOverlineColorAction*) pAction;
+
+ if( pA->IsSetting() )
+ m_rOuterFace.SetOverlineColor( pA->GetColor() );
+ else
+ m_rOuterFace.SetOverlineColor();
+ }
+ break;
+
+ case( META_TEXTFILLCOLOR_ACTION ):
+ {
+ const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pAction;
+
+ if( pA->IsSetting() )
+ m_rOuterFace.SetTextFillColor( pA->GetColor() );
+ else
+ m_rOuterFace.SetTextFillColor();
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ {
+ const MetaTextColorAction* pA = (const MetaTextColorAction*) pAction;
+ m_rOuterFace.SetTextColor( pA->GetColor() );
+ }
+ break;
+
+ case( META_TEXTALIGN_ACTION ):
+ {
+ const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pAction;
+ m_rOuterFace.SetTextAlign( pA->GetTextAlign() );
+ }
+ break;
+
+ case( META_FONT_ACTION ):
+ {
+ const MetaFontAction* pA = (const MetaFontAction*) pAction;
+ m_rOuterFace.SetFont( pA->GetFont() );
+ }
+ break;
+
+ case( META_PUSH_ACTION ):
+ {
+ const MetaPushAction* pA = (const MetaPushAction*) pAction;
+
+ pDummyVDev->Push( pA->GetFlags() );
+ m_rOuterFace.Push( pA->GetFlags() );
+ }
+ break;
+
+ case( META_POP_ACTION ):
+ {
+ pDummyVDev->Pop();
+ m_rOuterFace.Pop();
+ }
+ break;
+
+ case( META_LAYOUTMODE_ACTION ):
+ {
+ const MetaLayoutModeAction* pA = (const MetaLayoutModeAction*) pAction;
+ m_rOuterFace.SetLayoutMode( pA->GetLayoutMode() );
+ }
+ break;
+
+ case META_TEXTLANGUAGE_ACTION:
+ {
+ const MetaTextLanguageAction* pA = (const MetaTextLanguageAction*) pAction;
+ m_rOuterFace.SetDigitLanguage( pA->GetTextLanguage() );
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pAction;
+ m_rOuterFace.DrawWallpaper( pA->GetRect(), pA->GetWallpaper() );
+ }
+ break;
+
+ case( META_RASTEROP_ACTION ):
+ {
+ // !!! >>> we don't want to support this actions
+ }
+ break;
+
+ case( META_REFPOINT_ACTION ):
+ {
+ // !!! >>> we don't want to support this actions
+ }
+ break;
+
+ default:
+ // #i24604# Made assertion fire only once per
+ // metafile. The asserted actions here are all
+ // deprecated
+ if( !bAssertionFired )
+ {
+ bAssertionFired = true;
+ DBG_ERROR( "PDFExport::ImplWriteActions: deprecated and unsupported MetaAction encountered" );
+ }
+ break;
+ }
+ i++;
+ }
+ }
+
+ delete pPrivateDevice;
+}
+
+
diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx
index f6bd81ef1bea..60ba51191769 100644
--- a/vcl/source/gdi/print3.cxx
+++ b/vcl/source/gdi/print3.cxx
@@ -559,7 +559,7 @@ bool Printer::StartJob( const rtl::OUString& i_rJobName, boost::shared_ptr<vcl::
mnCurPage = 1;
mnCurPrintPage = 1;
mbPrinting = TRUE;
- if( ImplGetSVData()->maGDIData.mbPrinterPullModel )
+ if( GetCapabilities( PRINTER_CAPABILITIES_USEPULLMODEL ) )
{
mbJobActive = TRUE;
// sallayer does all necessary page printing
@@ -1522,6 +1522,11 @@ void PrinterController::createProgressDialog()
mpImplData->mpProgress->reset();
}
+bool PrinterController::isProgressCanceled()
+{
+ return mpImplData->mpProgress && mpImplData->mpProgress->isCanceled();
+}
+
void PrinterController::setMultipage( const MultiPageSetup& i_rMPS )
{
mpImplData->maMultiPage = i_rMPS;
diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx
index 4490bfb3dbeb..ff6492fd48e3 100644
--- a/vcl/source/window/printdlg.cxx
+++ b/vcl/source/window/printdlg.cxx
@@ -2573,6 +2573,7 @@ void PrintProgressDialog::tick()
void PrintProgressDialog::reset()
{
+ mbCanceled = false;
setProgress( 0 );
}
diff --git a/vcl/unx/inc/salprn.h b/vcl/unx/inc/salprn.h
index fa68f1b38e73..6e6ca0a2f1cc 100644
--- a/vcl/unx/inc/salprn.h
+++ b/vcl/unx/inc/salprn.h
@@ -71,6 +71,7 @@ public:
bool m_bFax:1;
bool m_bPdf:1;
bool m_bSwallowFaxNo:1;
+ bool m_bIsPDFWriterJob:1;
PspGraphics* m_pGraphics;
psp::PrinterJob m_aPrintJob;
psp::JobData m_aJobData;
@@ -91,6 +92,11 @@ public:
bool bCollate,
bool bDirect,
ImplJobSetup* pSetupData );
+ virtual BOOL StartJob( const String*,
+ const String&,
+ const String&,
+ ImplJobSetup*,
+ vcl::PrinterController& i_rController );
virtual BOOL EndJob();
virtual BOOL AbortJob();
virtual SalGraphics* StartPage( ImplJobSetup* pSetupData, BOOL bNewJobData );
diff --git a/vcl/unx/source/gdi/salprnpsp.cxx b/vcl/unx/source/gdi/salprnpsp.cxx
index 8617bc4e5bfa..b9e3cec07e00 100644
--- a/vcl/unx/source/gdi/salprnpsp.cxx
+++ b/vcl/unx/source/gdi/salprnpsp.cxx
@@ -54,6 +54,8 @@
#include "vcl/svapp.hxx"
#include "vcl/jobset.h"
#include "vcl/print.h"
+#include "vcl/print.hxx"
+#include "vcl/pdfwriter.hxx"
#include "vcl/salptype.hxx"
#include "vcl/printerinfomanager.hxx"
@@ -63,6 +65,7 @@
using namespace psp;
using namespace rtl;
+using namespace com::sun::star;
/*
* static helpers
@@ -892,9 +895,26 @@ ULONG PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT
case PRINTER_CAPABILITIES_FAX:
return PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "fax" ) ? 1 : 0;
case PRINTER_CAPABILITIES_PDF:
- return PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "pdf" ) ? 1 : 0;
+ if( PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "pdf" ) )
+ return 1;
+ else
+ {
+ // see if the PPD contains a value to set Collate to True
+ JobData aData = PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName );
+ if( pJobSetup->mpDriverData )
+ JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
+ return aData.m_nPDFDevice > 0 ? 1 : 0;
+ }
case PRINTER_CAPABILITIES_EXTERNALDIALOG:
return PrinterInfoManager::get().checkFeatureToken( pJobSetup->maPrinterName, "external_dialog" ) ? 1 : 0;
+ case PRINTER_CAPABILITIES_USEPULLMODEL:
+ {
+ // see if the PPD contains a value to set Collate to True
+ JobData aData = PrinterInfoManager::get().getPrinterInfo( pJobSetup->maPrinterName );
+ if( pJobSetup->mpDriverData )
+ JobData::constructFromStreamBuffer( pJobSetup->mpDriverData, pJobSetup->mnDriverDataLen, aData );
+ return aData.m_nPDFDevice > 0 ? 1 : 0;
+ }
default: break;
};
return 0;
@@ -910,6 +930,7 @@ ULONG PspSalInfoPrinter::GetCapabilities( const ImplJobSetup* pJobSetup, USHORT
: m_bFax( false ),
m_bPdf( false ),
m_bSwallowFaxNo( false ),
+ m_bIsPDFWriterJob( false ),
m_pGraphics( NULL ),
m_nCopies( 1 ),
m_bCollate( false ),
@@ -1021,22 +1042,28 @@ BOOL PspSalPrinter::StartJob(
BOOL PspSalPrinter::EndJob()
{
- BOOL bSuccess = m_aPrintJob.EndJob();
-
- if( bSuccess )
+ BOOL bSuccess = FALSE;
+ if( m_bIsPDFWriterJob )
+ bSuccess = TRUE;
+ else
{
- // check for fax
- if( m_bFax )
- {
+ bSuccess = m_aPrintJob.EndJob();
- const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
- // sendAFax removes the file after use
- bSuccess = sendAFax( m_aFaxNr, m_aTmpFile, rInfo.m_aCommand );
- }
- else if( m_bPdf )
+ if( bSuccess )
{
- const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
- bSuccess = createPdf( m_aFileName, m_aTmpFile, rInfo.m_aCommand );
+ // check for fax
+ if( m_bFax )
+ {
+
+ const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
+ // sendAFax removes the file after use
+ bSuccess = sendAFax( m_aFaxNr, m_aTmpFile, rInfo.m_aCommand );
+ }
+ else if( m_bPdf )
+ {
+ const PrinterInfo& rInfo( PrinterInfoManager::get().getPrinterInfo( m_aJobData.m_aPrinterName ) );
+ bSuccess = createPdf( m_aFileName, m_aTmpFile, rInfo.m_aCommand );
+ }
}
}
vcl_sal::PrinterUpdate::jobEnded();
@@ -1089,6 +1116,156 @@ ULONG PspSalPrinter::GetErrorCode()
return 0;
}
+// -----------------------------------------------------------------------
+
+BOOL PspSalPrinter::StartJob( const String* i_pFileName, const String& i_rJobName, const String& i_rAppName,
+ ImplJobSetup* i_pSetupData, vcl::PrinterController& i_rController )
+{
+ OSL_TRACE( "StartJob with controller: pFilename = %s", i_pFileName ? rtl::OUStringToOString( *i_pFileName, RTL_TEXTENCODING_UTF8 ).getStr() : "<nil>" );
+ // mark for endjob
+ m_bIsPDFWriterJob = true;
+ // reset IsLastPage
+ i_rController.setLastPage( sal_False );
+
+ // update job data
+ if( i_pSetupData )
+ JobData::constructFromStreamBuffer( i_pSetupData->mpDriverData, i_pSetupData->mnDriverDataLen, m_aJobData );
+
+ OSL_ASSERT( m_aJobData.m_nPDFDevice > 0 );
+ m_aJobData.m_nPDFDevice = 1;
+
+ // do we want a progress panel ?
+ // possibly create one job for collated output
+ sal_Bool bSinglePrintJobs = sal_False;
+ beans::PropertyValue* pSingleValue = i_rController.getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintCollateAsSingleJobs" ) ) );
+ if( pSingleValue )
+ {
+ pSingleValue->Value >>= bSinglePrintJobs;
+ }
+
+ m_aJobData.m_nCopies = i_rController.getPrinter()->GetCopyCount();
+ int nJobs = 1;
+ if( bSinglePrintJobs )
+ {
+ nJobs = m_aJobData.m_nCopies;
+ m_aJobData.m_nCopies = 1;
+ }
+
+ // notify start of real print job
+ i_rController.jobStarted();
+
+ // produce PDF file
+ OUString aPDFUrl;
+ if( i_pFileName )
+ aPDFUrl = *i_pFileName;
+ else
+ osl_createTempFile( NULL, NULL, &aPDFUrl.pData );
+ if( aPDFUrl.compareToAscii( "file:", 5 ) != 0 )
+ {
+ // this is not a file URL, but it should
+ // form it into a osl friendly file URL
+ rtl::OUString aTmp;
+ osl_getFileURLFromSystemPath( aPDFUrl.pData, &aTmp.pData );
+ aPDFUrl = aTmp;
+ }
+
+ // setup PDFWriter
+
+ vcl::PDFWriter::PDFWriterContext aContext;
+ aContext.URL = aPDFUrl;
+ aContext.Version = vcl::PDFWriter::PDF_1_4;
+ aContext.Tagged = false;
+ aContext.EmbedStandardFonts = true;
+ aContext.Encrypt = false;
+ aContext.DocumentLocale = Application::GetSettings().GetLocale();
+
+ vcl::PDFDocInfo aDocInfo;
+ aDocInfo.Title = i_rJobName;
+ aDocInfo.Creator = i_rAppName;
+ aDocInfo.Producer = i_rAppName;
+
+ vcl::PDFWriter aPDFWriter( aContext );
+ aPDFWriter.SetDocInfo( aDocInfo );
+ vcl::PDFWriter::PlayMetafileContext aMtfContext;
+ aMtfContext.m_bOnlyLosslessCompression = true;
+
+ boost::shared_ptr<Printer> pPrinter( i_rController.getPrinter() );
+ int nAllPages = i_rController.getFilteredPageCount();
+ i_rController.createProgressDialog();
+ bool bAborted = false;
+ for( int nPage = 0; nPage < nAllPages && ! bAborted; nPage++ )
+ {
+ if( nPage == nAllPages-1 )
+ i_rController.setLastPage( sal_True );
+
+ // get the pages metafile
+ GDIMetaFile aPageFile;
+ vcl::PrinterController::PageSize aPageSize = i_rController.getFilteredPageFile( nPage, aPageFile );
+ if( i_rController.isProgressCanceled() )
+ {
+ bAborted = true;
+ if( nPage != nAllPages-1 )
+ {
+ i_rController.createProgressDialog();
+ i_rController.setLastPage( sal_True );
+ i_rController.getFilteredPageFile( nPage, aPageFile );
+ }
+ }
+ else
+ {
+ pPrinter->SetMapMode( MapMode( MAP_100TH_MM ) );
+ pPrinter->SetPaperSizeUser( aPageSize.aSize, true );
+ Size aRealSize( pPrinter->GetPaperSize() );
+
+ aPDFWriter.NewPage( TenMuToPt( aRealSize.Width() ),
+ TenMuToPt( aRealSize.Height() ),
+ vcl::PDFWriter::Portrait );
+
+ aPDFWriter.PlayMetafile( aPageFile, aMtfContext, NULL );
+ }
+ }
+
+ aPDFWriter.Emit();
+
+ if( ! i_pFileName && ! bAborted )
+ {
+ oslFileHandle pFile = NULL;
+ osl_openFile( aContext.URL.pData, &pFile, osl_File_OpenFlag_Read );
+ if( pFile )
+ {
+ osl_setFilePos( pFile, osl_Pos_Absolut, 0 );
+ std::vector< char > buffer( 0x10000, 0 );
+ for( int nCurJob = 0; nCurJob < nJobs; nCurJob++ )
+ {
+ FILE* fp = PrinterInfoManager::get().startSpool( i_pSetupData->maPrinterName, i_rController.isDirectPrint() );
+ if( fp )
+ {
+ sal_uInt64 nBytesRead = 0;
+ do
+ {
+ osl_readFile( pFile, &buffer[0], buffer.size(), &nBytesRead );
+ if( nBytesRead > 0 )
+ fwrite( &buffer[0], 1, nBytesRead, fp );
+ } while( nBytesRead == buffer.size() );
+ PrinterInfoManager::get().endSpool( i_pSetupData->maPrinterName, i_rJobName, fp, m_aJobData );
+ }
+ }
+ osl_closeFile( pFile );
+ }
+ }
+
+ // job has been spooled
+ i_rController.setJobState( bAborted ? view::PrintableState_JOB_ABORTED : view::PrintableState_JOB_SPOOLED );
+
+ // clean up the PDF file
+ if( ! i_pFileName || bAborted )
+ osl_removeFile( aPDFUrl.pData );
+
+ return TRUE;
+}
+
+
+
/*
* vcl::PrinterUpdate
*/
diff --git a/vcl/unx/source/printer/cupsmgr.cxx b/vcl/unx/source/printer/cupsmgr.cxx
index e245b2548c79..c4fcf433d349 100644
--- a/vcl/unx/source/printer/cupsmgr.cxx
+++ b/vcl/unx/source/printer/cupsmgr.cxx
@@ -524,12 +524,18 @@ void CUPSManager::initialize()
// introduced in dests with 1.2
// this is needed to check for %%IncludeFeature support
// (#i65684#, #i65491#)
+ bool bUsePDF = false;
cups_dest_t* pDest = ((cups_dest_t*)m_pDests);
const char* pOpt = m_pCUPSWrapper->cupsGetOption( "printer-info",
pDest->num_options,
pDest->options );
if( pOpt )
+ {
m_bUseIncludeFeature = true;
+ bUsePDF = true;
+ if( m_aGlobalDefaults.m_nPSLevel == 0 && m_aGlobalDefaults.m_nPDFDevice == 0 )
+ m_aGlobalDefaults.m_nPDFDevice = 1;
+ }
// do not send include JobPatch; CUPS will insert that itself
// TODO: currently unknwon which versions of CUPS insert JobPatches
// so currently it is assumed CUPS = don't insert JobPatch files
@@ -593,6 +599,8 @@ void CUPSManager::initialize()
aPrinter.m_aInfo.m_pParser = c_it->second.getParser();
aPrinter.m_aInfo.m_aContext = c_it->second;
}
+ if( bUsePDF && aPrinter.m_aInfo.m_nPSLevel == 0 && aPrinter.m_aInfo.m_nPDFDevice == 0 )
+ aPrinter.m_aInfo.m_nPDFDevice = 1;
aPrinter.m_aInfo.m_aDriverName = aBuf.makeStringAndClear();
aPrinter.m_bModified = false;
@@ -880,6 +888,12 @@ void CUPSManager::getOptionsFromDocumentSetup( const JobData& rJob, int& rNumOpt
}
}
}
+
+ if( rJob.m_nPDFDevice > 0 && rJob.m_nCopies > 1 )
+ {
+ rtl::OString aVal( rtl::OString::valueOf( sal_Int32( rJob.m_nCopies ) ) );
+ rNumOptions = m_pCUPSWrapper->cupsAddOption( "copies", aVal.getStr(), rNumOptions, (cups_option_t**)rOptions );
+ }
}
int CUPSManager::endSpool( const OUString& rPrintername, const OUString& rJobTitle, FILE* pFile, const JobData& rDocumentJobData )
diff --git a/vcl/unx/source/printer/jobdata.cxx b/vcl/unx/source/printer/jobdata.cxx
index a1bca9441f77..019c1da1fbc9 100644
--- a/vcl/unx/source/printer/jobdata.cxx
+++ b/vcl/unx/source/printer/jobdata.cxx
@@ -51,6 +51,7 @@ JobData& JobData::operator=(const JobData& rRight)
m_pParser = rRight.m_pParser;
m_aContext = rRight.m_aContext;
m_nPSLevel = rRight.m_nPSLevel;
+ m_nPDFDevice = rRight.m_nPDFDevice;
m_nColorDevice = rRight.m_nColorDevice;
if( ! m_pParser && m_aPrinterName.getLength() )
@@ -128,6 +129,10 @@ bool JobData::getStreamBuffer( void*& pData, int& bytes )
aLine += ByteString::CreateFromInt32( m_nPSLevel );
aStream.WriteLine( aLine );
+ aLine = "pdfdevice=";
+ aLine += ByteString::CreateFromInt32( m_nPDFDevice );
+ aStream.WriteLine( aLine );
+
aLine = "colordevice=";
aLine += ByteString::CreateFromInt32( m_nColorDevice );
aStream.WriteLine( aLine );
@@ -158,6 +163,7 @@ bool JobData::constructFromStreamBuffer( void* pData, int bytes, JobData& rJobDa
bool bColorDepth = false;
bool bColorDevice = false;
bool bPSLevel = false;
+ bool bPDFDevice = false;
while( ! aStream.IsEof() )
{
aStream.ReadLine( aLine );
@@ -202,6 +208,11 @@ bool JobData::constructFromStreamBuffer( void* pData, int bytes, JobData& rJobDa
bPSLevel = true;
rJobData.m_nPSLevel = aLine.Copy( 8 ).ToInt32();
}
+ else if( aLine.CompareTo( "pdfdevice=", 10 ) == COMPARE_EQUAL )
+ {
+ bPDFDevice = true;
+ rJobData.m_nPDFDevice = aLine.Copy( 10 ).ToInt32();
+ }
else if( aLine.Equals( "PPDContexData" ) )
{
if( bPrinter )
@@ -222,5 +233,5 @@ bool JobData::constructFromStreamBuffer( void* pData, int bytes, JobData& rJobDa
}
}
- return bVersion && bPrinter && bOrientation && bCopies && bContext && bMargin && bPSLevel && bColorDevice && bColorDepth;
+ return bVersion && bPrinter && bOrientation && bCopies && bContext && bMargin && bPSLevel && bPDFDevice && bColorDevice && bColorDepth;
}
diff --git a/vcl/unx/source/printer/printerinfomanager.cxx b/vcl/unx/source/printer/printerinfomanager.cxx
index e1d499c40ca5..84997d11ac56 100644
--- a/vcl/unx/source/printer/printerinfomanager.cxx
+++ b/vcl/unx/source/printer/printerinfomanager.cxx
@@ -283,6 +283,10 @@ void PrinterInfoManager::initialize()
if( aValue.Len() )
m_aGlobalDefaults.m_nPSLevel = aValue.ToInt32();
+ aValue = aConfig.ReadKey( "PDFDevice" );
+ if( aValue.Len() )
+ m_aGlobalDefaults.m_nPDFDevice = aValue.ToInt32();
+
aValue = aConfig.ReadKey( "PerformFontSubstitution" );
if( aValue.Len() )
{
@@ -494,6 +498,10 @@ void PrinterInfoManager::initialize()
if( aValue.Len() )
aPrinter.m_aInfo.m_nPSLevel = aValue.ToInt32();
+ aValue = aConfig.ReadKey( "PDFDevice" );
+ if( aValue.Len() )
+ aPrinter.m_aInfo.m_nPDFDevice = aValue.ToInt32();
+
aValue = aConfig.ReadKey( "PerformFontSubstitution" );
if( ! aValue.Equals( "0" ) && ! aValue.EqualsIgnoreCaseAscii( "false" ) )
aPrinter.m_aInfo.m_bPerformFontSubstitution = true;
@@ -758,6 +766,7 @@ bool PrinterInfoManager::writePrinterConfig()
pConfig->WriteKey( "Copies", ByteString::CreateFromInt32( it->second.m_aInfo.m_nCopies ) );
pConfig->WriteKey( "Orientation", it->second.m_aInfo.m_eOrientation == orientation::Landscape ? "Landscape" : "Portrait" );
pConfig->WriteKey( "PSLevel", ByteString::CreateFromInt32( it->second.m_aInfo.m_nPSLevel ) );
+ pConfig->WriteKey( "PDFDevice", ByteString::CreateFromInt32( it->second.m_aInfo.m_nPDFDevice ) );
pConfig->WriteKey( "ColorDevice", ByteString::CreateFromInt32( it->second.m_aInfo.m_nColorDevice ) );
pConfig->WriteKey( "ColorDepth", ByteString::CreateFromInt32( it->second.m_aInfo.m_nColorDepth ) );
aValue = ByteString::CreateFromInt32( it->second.m_aInfo.m_nLeftMarginAdjust );
@@ -845,9 +854,10 @@ bool PrinterInfoManager::addPrinter( const OUString& rPrinterName, const OUStrin
m_aPrinters[ rPrinterName ] = aPrinter;
bSuccess = true;
#if OSL_DEBUG_LEVEL > 1
- fprintf( stderr, "new printer %s, level = %d, colordevice = %d, depth = %d\n",
+ fprintf( stderr, "new printer %s, level = %d, pdfdevice = %d, colordevice = %d, depth = %d\n",
OUStringToOString( rPrinterName, osl_getThreadTextEncoding() ).getStr(),
m_aPrinters[rPrinterName].m_aInfo.m_nPSLevel,
+ m_aPrinters[rPrinterName].m_aInfo.m_nPDFDevice,
m_aPrinters[rPrinterName].m_aInfo.m_nColorDevice,
m_aPrinters[rPrinterName].m_aInfo.m_nColorDepth );
#endif
diff --git a/vcl/unx/source/printergfx/printerjob.cxx b/vcl/unx/source/printergfx/printerjob.cxx
index 5e18849b8dfe..c69a0771655d 100644
--- a/vcl/unx/source/printergfx/printerjob.cxx
+++ b/vcl/unx/source/printergfx/printerjob.cxx
@@ -341,7 +341,8 @@ PrinterJob::~PrinterJob ()
delete mpJobTrailer;
// XXX should really call osl::remove routines
- removeSpoolDir (maSpoolDirName);
+ if( maSpoolDirName.getLength() )
+ removeSpoolDir (maSpoolDirName);
// osl::Directory::remove (maSpoolDirName);
}