summaryrefslogtreecommitdiff
path: root/filter/source/flash
diff options
context:
space:
mode:
authorChristian Lippka <cl@openoffice.org>2002-11-21 13:58:04 +0000
committerChristian Lippka <cl@openoffice.org>2002-11-21 13:58:04 +0000
commitac9fe009be9867ffda85990425d054a759f42caf (patch)
treeceec1d86d460038b845fd5fad22ace6bbf67b90f /filter/source/flash
parent7540c56ec699d18b2a30923a4c15a0ce2232bb40 (diff)
#105361# adding augustus changes and putting flash into srx644
Diffstat (limited to 'filter/source/flash')
-rw-r--r--filter/source/flash/impswfdialog.cxx56
-rw-r--r--filter/source/flash/impswfdialog.hrc18
-rw-r--r--filter/source/flash/impswfdialog.hxx21
-rw-r--r--filter/source/flash/impswfdialog.src131
-rw-r--r--filter/source/flash/makefile.mk16
-rw-r--r--filter/source/flash/swfexporter.cxx804
-rw-r--r--filter/source/flash/swfexporter.hxx270
-rw-r--r--filter/source/flash/swffilter.cxx601
-rw-r--r--filter/source/flash/swfuno.cxx170
-rw-r--r--filter/source/flash/swfwriter.cxx704
-rw-r--r--filter/source/flash/swfwriter.hxx522
-rw-r--r--filter/source/flash/swfwriter1.cxx1870
-rw-r--r--filter/source/flash/swfwriter2.cxx727
13 files changed, 5874 insertions, 36 deletions
diff --git a/filter/source/flash/impswfdialog.cxx b/filter/source/flash/impswfdialog.cxx
index 71425b19af81..a19c33126cc3 100644
--- a/filter/source/flash/impswfdialog.cxx
+++ b/filter/source/flash/impswfdialog.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: impswfdialog.cxx,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: cl $ $Date: 2002-10-30 12:34:34 $
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:01 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -74,6 +74,21 @@ ImpSWFDialog::ImpSWFDialog( Window* pParent, ResMgr& rResMgr, Sequence< Property
ModalDialog( pParent, ResId( DLG_OPTIONS, &rResMgr ) ),
maFiDescr( this, ResId( FI_DESCR ) ),
maNumFldQuality( this, ResId( NUM_FLD_QUALITY ) ),
+ maFiExportAllDescr( this, ResId( FI_EXPORT_ALL_DESCR ) ),
+ maCheckExportAll( this, ResId( BOOL_EXPORT_ALL ) ),
+ maFiExportBackgroundsDescr( this, ResId( FI_EXPORT_BACKGROUNDS_DESCR ) ),
+ maCheckExportBackgrounds( this, ResId( BOOL_EXPORT_BACKGROUNDS ) ),
+ maFiExportBackgroundObjectsDescr( this, ResId( FI_EXPORT_BACKGROUND_OBJECTS_DESCR ) ),
+ maCheckExportBackgroundObjects( this, ResId( BOOL_EXPORT_BACKGROUND_OBJECTS ) ),
+ maFiExportSlideContentsDescr( this, ResId( FI_EXPORT_SLIDE_CONTENTS_DESCR ) ),
+ maCheckExportSlideContents( this, ResId( BOOL_EXPORT_SLIDE_CONTENTS ) ),
+ maFiExportSoundDescr( this, ResId( FI_EXPORT_SOUND_DESCR ) ),
+ maCheckExportSound( this, ResId( BOOL_EXPORT_SOUND ) ),
+ maFiExportOLEAsJPEGDescr( this, ResId( FI_EXPORT_OLE_AS_JPEG_DESCR ) ),
+ maCheckExportOLEAsJPEG( this, ResId( BOOL_EXPORT_OLE_AS_JPEG ) ),
+ maFiExportMultipleFilesDescr( this, ResId( FI_EXPORT_MULTIPLE_FILES_DESCR ) ),
+ maCheckExportMultipleFiles( this, ResId( BOOL_EXPORT_MULTIPLE_FILES ) ),
+
maBtnOK( this, ResId( BTN_OK ) ),
maBtnCancel( this, ResId( BTN_CANCEL ) ),
maBtnHelp( this, ResId( BTN_HELP ) ),
@@ -82,6 +97,20 @@ ImpSWFDialog::ImpSWFDialog( Window* pParent, ResMgr& rResMgr, Sequence< Property
const ULONG nCompressMode = maConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "CompressMode" ) ), 75 );
maNumFldQuality.SetValue( nCompressMode );
+ maCheckExportAll.Check();
+ maCheckExportSlideContents.Check();
+ maCheckExportSound.Check();
+
+ maCheckExportAll.SetToggleHdl( LINK( this, ImpSWFDialog, OnToggleCheckbox ) );
+
+ maCheckExportBackgrounds.Disable(); maFiExportBackgroundsDescr.Disable();
+ maCheckExportBackgroundObjects.Disable(); maFiExportBackgroundObjectsDescr.Disable();
+ maCheckExportSlideContents.Disable(); maFiExportSlideContentsDescr.Disable();
+
+#ifdef AUGUSTUS
+ maCheckExportMultipleFiles.Check();
+#endif
+
FreeResource();
}
@@ -97,8 +126,31 @@ Sequence< PropertyValue > ImpSWFDialog::GetFilterData()
{
sal_Int32 nCompressMode = (sal_Int32)maNumFldQuality.GetValue();
maConfigItem.WriteInt32( OUString( RTL_CONSTASCII_USTRINGPARAM( "CompressMode" ) ), nCompressMode );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportAll" ) ), maCheckExportAll.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportBackgrounds" ) ), maCheckExportBackgrounds.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportBackgroundObjects" ) ), maCheckExportBackgroundObjects.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportSlideContents" ) ), maCheckExportSlideContents.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportSound" ) ), maCheckExportSound.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportOLEAsJPEG" ) ), maCheckExportOLEAsJPEG.IsChecked() );
+ maConfigItem.WriteBool( OUString( RTL_CONSTASCII_USTRINGPARAM( "ExportMultipleFiles" ) ), maCheckExportMultipleFiles.IsChecked() );
+
Sequence< PropertyValue > aRet( maConfigItem.GetFilterData() );
return aRet;
}
+// AS: This is called whenever the user toggles one of the checkboxes
+IMPL_LINK( ImpSWFDialog, OnToggleCheckbox, CheckBox*, pBox )
+{
+ if (pBox == &maCheckExportAll)
+ {
+ maCheckExportBackgrounds.Enable(!maCheckExportBackgrounds.IsEnabled());
+ maFiExportBackgroundsDescr.Enable(!maFiExportBackgroundsDescr.IsEnabled());
+ maCheckExportBackgroundObjects.Enable(!maCheckExportBackgroundObjects.IsEnabled());
+ maFiExportBackgroundObjectsDescr.Enable(!maFiExportBackgroundObjectsDescr.IsEnabled());
+ maCheckExportSlideContents.Enable(!maCheckExportSlideContents.IsEnabled());
+ maFiExportSlideContentsDescr.Enable(!maFiExportSlideContentsDescr.IsEnabled());
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/filter/source/flash/impswfdialog.hrc b/filter/source/flash/impswfdialog.hrc
index 64e309902540..b8575ac98084 100644
--- a/filter/source/flash/impswfdialog.hrc
+++ b/filter/source/flash/impswfdialog.hrc
@@ -2,9 +2,9 @@
*
* $RCSfile: impswfdialog.hrc,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: cl $ $Date: 2002-10-24 16:24:23 $
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:01 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -65,4 +65,18 @@
#define BTN_CANCEL 1
#define BTN_HELP 1
#define FI_DESCR 1
+#define FI_EXPORT_ALL_DESCR 2
+#define FI_EXPORT_BACKGROUNDS_DESCR 3
+#define FI_EXPORT_BACKGROUND_OBJECTS_DESCR 4
+#define FI_EXPORT_SLIDE_CONTENTS_DESCR 5
+#define FI_EXPORT_SOUND_DESCR 6
+#define FI_EXPORT_OLE_AS_JPEG_DESCR 7
+#define FI_EXPORT_MULTIPLE_FILES_DESCR 8
#define NUM_FLD_QUALITY 1
+#define BOOL_EXPORT_ALL 1
+#define BOOL_EXPORT_BACKGROUNDS 2
+#define BOOL_EXPORT_BACKGROUND_OBJECTS 3
+#define BOOL_EXPORT_SLIDE_CONTENTS 4
+#define BOOL_EXPORT_SOUND 5
+#define BOOL_EXPORT_OLE_AS_JPEG 6
+#define BOOL_EXPORT_MULTIPLE_FILES 7 \ No newline at end of file
diff --git a/filter/source/flash/impswfdialog.hxx b/filter/source/flash/impswfdialog.hxx
index 00147cdb8316..17acf61fb24d 100644
--- a/filter/source/flash/impswfdialog.hxx
+++ b/filter/source/flash/impswfdialog.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: impswfdialog.hxx,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: cl $ $Date: 2002-10-24 16:24:24 $
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:01 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -93,12 +93,29 @@ class ImpSWFDialog : public ModalDialog
private:
FixedInfo maFiDescr;
NumericField maNumFldQuality;
+ FixedInfo maFiExportAllDescr;
+ CheckBox maCheckExportAll;
+ FixedInfo maFiExportBackgroundsDescr;
+ CheckBox maCheckExportBackgrounds;
+ FixedInfo maFiExportBackgroundObjectsDescr;
+ CheckBox maCheckExportBackgroundObjects;
+ FixedInfo maFiExportSlideContentsDescr;
+ CheckBox maCheckExportSlideContents;
+ FixedInfo maFiExportSoundDescr;
+ CheckBox maCheckExportSound;
+ FixedInfo maFiExportOLEAsJPEGDescr;
+ CheckBox maCheckExportOLEAsJPEG;
+ FixedInfo maFiExportMultipleFilesDescr;
+ CheckBox maCheckExportMultipleFiles;
+
OKButton maBtnOK;
CancelButton maBtnCancel;
HelpButton maBtnHelp;
FilterConfigItem maConfigItem;
+ DECL_LINK( OnToggleCheckbox, CheckBox* );
+
public:
ImpSWFDialog( Window* pParent, ResMgr& rResMgr,
com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rFilterData );
diff --git a/filter/source/flash/impswfdialog.src b/filter/source/flash/impswfdialog.src
index 924b86f2b921..8b5ae964e41d 100644
--- a/filter/source/flash/impswfdialog.src
+++ b/filter/source/flash/impswfdialog.src
@@ -2,9 +2,9 @@
*
* $RCSfile: impswfdialog.src,v $
*
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
*
- * last change: $Author: cl $ $Date: 2002-10-24 16:24:25 $
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:02 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -63,7 +63,7 @@
ModalDialog DLG_OPTIONS
{
- Size = MAP_APPFONT ( 159 , 92 ) ;
+ Size = MAP_APPFONT ( 200 , 200 ) ;
OutputSize = TRUE ;
SVLook = TRUE ;
Moveable = TRUE ;
@@ -72,25 +72,6 @@ ModalDialog DLG_OPTIONS
Text [ ENGLISH ] = "Flash Optionen" ;
Text [ english_us ] = "Flash Options" ;
- OKButton BTN_OK
- {
- Pos = MAP_APPFONT ( 103 , 6 ) ;
- Size = MAP_APPFONT ( 50 , 14 ) ;
- TabStop = TRUE ;
- DefButton = TRUE ;
- };
- CancelButton BTN_CANCEL
- {
- Pos = MAP_APPFONT ( 103 , 23 ) ;
- Size = MAP_APPFONT ( 50 , 14 ) ;
- TabStop = TRUE ;
- };
- HelpButton BTN_HELP
- {
- Pos = MAP_APPFONT ( 103 , 43 ) ;
- Size = MAP_APPFONT ( 50 , 14 ) ;
- TabStop = TRUE ;
- };
FixedText FI_DESCR
{
Pos = MAP_APPFONT ( 12 , 14 ) ;
@@ -135,4 +116,110 @@ ModalDialog DLG_OPTIONS
Last = 100 ;
Repeat = TRUE ;
};
+ CheckBox BOOL_EXPORT_ALL
+ {
+ Pos = MAP_APPFONT ( 12 , 65 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_ALL_DESCR
+ {
+ Pos = MAP_APPFONT ( 25 , 65 ) ;
+ Size = MAP_APPFONT ( 150 , 16 ) ;
+ Text = "Export All Slides (Uncheck exports current slide)" ;
+ };
+ CheckBox BOOL_EXPORT_MULTIPLE_FILES
+ {
+ Pos = MAP_APPFONT ( 12 , 80 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_MULTIPLE_FILES_DESCR
+ {
+ Pos = MAP_APPFONT ( 25 , 80 ) ;
+ Size = MAP_APPFONT ( 150 , 16 ) ;
+ Text = "Export As Multiple Files" ;
+ };
+ CheckBox BOOL_EXPORT_BACKGROUNDS
+ {
+ Pos = MAP_APPFONT ( 22 , 95 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_BACKGROUNDS_DESCR
+ {
+ Pos = MAP_APPFONT ( 35 , 95 ) ;
+ Size = MAP_APPFONT ( 100 , 16 ) ;
+ Text = "Export Backgrounds" ;
+ };
+ CheckBox BOOL_EXPORT_BACKGROUND_OBJECTS
+ {
+ Pos = MAP_APPFONT ( 22 , 107) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_BACKGROUND_OBJECTS_DESCR
+ {
+ Pos = MAP_APPFONT ( 35 , 107) ;
+ Size = MAP_APPFONT ( 100 , 16 ) ;
+ Text = "Export Background Objects" ;
+ };
+ CheckBox BOOL_EXPORT_SLIDE_CONTENTS
+ {
+ Pos = MAP_APPFONT ( 22 , 119 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_SLIDE_CONTENTS_DESCR
+ {
+ Pos = MAP_APPFONT ( 35 , 119 ) ;
+ Size = MAP_APPFONT ( 100 , 16 ) ;
+ Text = "Export Slide Contents" ;
+ };
+ CheckBox BOOL_EXPORT_SOUND
+ {
+ Pos = MAP_APPFONT ( 12 , 134 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_SOUND_DESCR
+ {
+ Pos = MAP_APPFONT ( 25 , 134 ) ;
+ Size = MAP_APPFONT ( 100 , 16 ) ;
+ Text = "Export Verilogix Slide Annotations" ;
+ };
+ CheckBox BOOL_EXPORT_OLE_AS_JPEG
+ {
+ Pos = MAP_APPFONT ( 12 , 146 ) ;
+ Size = MAP_APPFONT ( 10 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ FixedText FI_EXPORT_OLE_AS_JPEG_DESCR
+ {
+ Pos = MAP_APPFONT ( 25 , 146 ) ;
+ Size = MAP_APPFONT ( 100 , 16 ) ;
+ Text = "Export OLE Objects as JPEG images" ;
+ };
+
+
+ OKButton BTN_OK
+ {
+ Pos = MAP_APPFONT ( 12 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ DefButton = TRUE ;
+ };
+ CancelButton BTN_CANCEL
+ {
+ Pos = MAP_APPFONT ( 70 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+ HelpButton BTN_HELP
+ {
+ Pos = MAP_APPFONT ( 140 , 180 ) ;
+ Size = MAP_APPFONT ( 50 , 14 ) ;
+ TabStop = TRUE ;
+ };
+
};
diff --git a/filter/source/flash/makefile.mk b/filter/source/flash/makefile.mk
index a7813ef83f72..646de1291bbe 100644
--- a/filter/source/flash/makefile.mk
+++ b/filter/source/flash/makefile.mk
@@ -2,9 +2,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.3 $
+# $Revision: 1.4 $
#
-# last change: $Author: cl $ $Date: 2002-10-24 16:24:26 $
+# last change: $Author: cl $ $Date: 2002-11-21 14:58:02 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
@@ -98,12 +98,12 @@ UNOTYPES=\
SRCFILES = impswfdialog.src
-SLOFILES= $(SLO)$/filter.obj \
- $(SLO)$/writer.obj \
- $(SLO)$/writer1.obj \
- $(SLO)$/writer2.obj \
- $(SLO)$/uno.obj \
- $(SLO)$/exporter.obj \
+SLOFILES= $(SLO)$/swffilter.obj \
+ $(SLO)$/swfwriter.obj \
+ $(SLO)$/swfwriter1.obj \
+ $(SLO)$/swfwriter2.obj \
+ $(SLO)$/swfuno.obj \
+ $(SLO)$/swfexporter.obj \
$(SLO)$/swfdialog.obj \
$(SLO)$/impswfdialog.obj
diff --git a/filter/source/flash/swfexporter.cxx b/filter/source/flash/swfexporter.cxx
new file mode 100644
index 000000000000..9d8d5c0f9b88
--- /dev/null
+++ b/filter/source/flash/swfexporter.cxx
@@ -0,0 +1,804 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfexporter.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:02 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _COM_SUN_STAR_AWT_RECTANGLE_HPP_
+#include <com/sun/star/awt/Rectangle.hpp>
+#endif
+#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
+#include <com/sun/star/beans/PropertyValue.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XMASTERPAGETARGET_HPP_
+#include <com/sun/star/drawing/XMasterPageTarget.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESSUPPLIER_HPP_
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
+#include <com/sun/star/container/XIndexAccess.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESSUPPLIER_HPP_
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DOCUMENT_XFILTER_HPP_
+#include <com/sun/star/document/XFilter.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_
+#include <com/sun/star/document/XExporter.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
+#include <com/sun/star/frame/XModel.hpp>
+#endif
+#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_
+#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
+#endif
+
+#ifndef _SV_GDIMTF_HXX
+#include <vcl/gdimtf.hxx>
+#endif
+
+#ifndef _UNOTOOLS_TEMPFILE_HXX
+#include <unotools/tempfile.hxx>
+#endif
+
+#ifndef _OSL_DIAGNOSE_H_
+#include <osl/diagnose.h>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _SV_METAACT_HXX
+#include <vcl/metaact.hxx>
+#endif
+
+#ifndef _WMF_HXX
+#include <svtools/wmf.hxx>
+#endif
+#ifndef _FILTER_HXX
+#include <svtools/Filter.hxx>
+#endif
+
+#include "swfexporter.hxx"
+#include "swfwriter.hxx"
+
+using rtl::OUString;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::presentation;
+using namespace ::com::sun::star::task;
+using namespace ::std;
+using namespace ::swf;
+
+using com::sun::star::lang::XMultiServiceFactory;
+using com::sun::star::io::XOutputStream;
+using com::sun::star::beans::PropertyValue;
+using com::sun::star::container::XIndexAccess;
+using com::sun::star::beans::XPropertySet;
+using com::sun::star::lang::XComponent;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::document::XExporter;
+using com::sun::star::document::XFilter;
+using com::sun::star::frame::XModel;
+
+// -----------------------------------------------------------------------------
+
+static const char* pszCurrentPageName = "current_page"; // TODO: Size optimize later?
+static const char* pszLastPageName = "last_page"; // TODO: Size optimize later?
+
+// -----------------------------------------------------------------------------
+
+PageInfo::PageInfo()
+: meFadeEffect( FadeEffect_NONE ),
+ meFadeSpeed( AnimationSpeed_MEDIUM ),
+ mnDuration( 0 ),
+ mnChange( 0 )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+PageInfo::~PageInfo()
+{
+ vector<ShapeInfo*>::iterator aIter( maShapesVector.begin() );
+ const vector<ShapeInfo*>::iterator aEnd( maShapesVector.end() );
+ while( aIter != aEnd )
+ {
+ delete (*aIter++);
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void PageInfo::addShape( ShapeInfo* pShapeInfo )
+{
+ maShapesVector.push_back( pShapeInfo );
+}
+
+
+// -----------------------------------------------------------------------------
+
+FlashExporter::FlashExporter(const Reference< XMultiServiceFactory > &rxMSF, sal_Int32 nJPEGCompressMode, sal_Bool bExportOLEAsJPEG)
+: mxMSF( rxMSF ), mpWriter( NULL ), mnJPEGcompressMode(nJPEGCompressMode), mbExportOLEAsJPEG(bExportOLEAsJPEG)
+{
+}
+
+// -----------------------------------------------------------------------------
+
+FlashExporter::~FlashExporter()
+{
+ Flush();
+}
+
+void FlashExporter::Flush()
+{
+ delete mpWriter;
+ mpWriter = NULL;
+
+ maPagesMap.clear();
+}
+
+// -----------------------------------------------------------------------------
+
+const sal_uInt16 cBackgroundDepth = 2;
+const sal_uInt16 cBackgroundObjectsDepth = 3;
+const sal_uInt16 cPageObjectsDepth = 4;
+const sal_uInt16 cWaitButtonDepth = 10;
+
+sal_Bool FlashExporter::exportAll( Reference< XComponent > xDoc, Reference< XOutputStream > &xOutputStream, Reference< XStatusIndicator> &xStatusIndicator )
+{
+ Reference< XDrawPagesSupplier > xDrawPagesSupplier(xDoc, UNO_QUERY);
+ if(!xDrawPagesSupplier.is())
+ return sal_False;
+
+ Reference< XIndexAccess > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY );
+ if(!xDrawPages.is())
+ return sal_False;
+
+ Reference< XDrawPage > xDrawPage;
+ xDrawPages->getByIndex(0) >>= xDrawPage;
+
+ Reference< XPropertySet > xProp( xDrawPage, UNO_QUERY );
+ try
+ {
+ xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= mnDocWidth;
+ xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= mnDocHeight;
+
+ delete mpWriter;
+ mpWriter = new Writer( 14400, 10800, mnDocWidth, mnDocHeight, mnJPEGcompressMode );
+ }
+ catch( exception& )
+ {
+ OSL_ASSERT( false );
+ }
+
+ const sal_Int32 nPageCount = xDrawPages->getCount();
+ sal_uInt16 nPage;
+ xStatusIndicator->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "Saving :" )), nPageCount);
+ for( nPage = 0; nPage < nPageCount; nPage++)
+ {
+ xStatusIndicator->setValue( nPage );
+ xDrawPages->getByIndex(nPage) >>= xDrawPage;
+
+ if( !xDrawPage.is())
+ continue;
+
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+ sal_Bool bVisible;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Visible") ) ) >>= bVisible;
+ if( !bVisible )
+ continue;
+
+ exportBackgrounds( xDrawPage, nPage, false );
+ exportBackgrounds( xDrawPage, nPage, true );
+
+ maPagesMap[nPage].mnForegroundID = mpWriter->startSprite();
+ exportDrawPageContents( xDrawPage, false );
+ mpWriter->endSprite();
+
+ // AS: If the background is different than the previous slide,
+ // we have to remove the old one and place the new one.
+ if (nPage)
+ {
+ if (maPagesMap[nPage].mnBackgroundID != maPagesMap[nPage-1].mnBackgroundID)
+ {
+ mpWriter->removeShape(cBackgroundDepth);
+ mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, cBackgroundDepth, 0, 0 );
+ }
+
+ if (maPagesMap[nPage].mnObjectsID != maPagesMap[nPage-1].mnObjectsID)
+ {
+ mpWriter->removeShape(cBackgroundObjectsDepth);
+ mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, cBackgroundObjectsDepth, 0, 0 );
+ }
+
+ // AS: Remove the Foreground of the previous slide.
+ mpWriter->removeShape(cPageObjectsDepth);
+ }
+ else
+ {
+ mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, cBackgroundDepth, 0, 0 );
+ mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, cBackgroundObjectsDepth, 0, 0 );
+ }
+
+ mpWriter->placeShape( maPagesMap[nPage].mnForegroundID, cPageObjectsDepth, 0, 0 );
+
+ mpWriter->waitOnClick( cWaitButtonDepth );
+ mpWriter->showFrame();
+ }
+
+ mpWriter->removeShape( cBackgroundDepth );
+ mpWriter->removeShape( cBackgroundObjectsDepth );
+ mpWriter->removeShape( cPageObjectsDepth );
+ mpWriter->gotoFrame( 0 );
+ mpWriter->showFrame();
+
+ mpWriter->storeTo( xOutputStream );
+
+ return sal_True;
+}
+
+
+sal_Bool FlashExporter::exportSlides( Reference< XDrawPage > xDrawPage, Reference< XOutputStream > &xOutputStream, sal_uInt16 nPage)
+{
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+ if( !xDrawPage.is() || !xPropSet.is() )
+ return sal_False;
+
+ try
+ {
+ if( NULL == mpWriter )
+ {
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= mnDocWidth;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= mnDocHeight;
+
+ mpWriter = new Writer( 14400, 10800, mnDocWidth, mnDocHeight, mnJPEGcompressMode );
+ }
+
+ sal_Bool bVisible;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Visible") ) ) >>= bVisible;
+ if( !bVisible )
+ return sal_False;
+ }
+ catch( exception& )
+ {
+ OSL_ASSERT( false );
+ }
+
+ exportDrawPageContents(xDrawPage, true);
+
+ mpWriter->storeTo( xOutputStream );
+
+ return sal_True;
+}
+
+sal_uInt16 FlashExporter::exportBackgrounds( Reference< XDrawPage > xDrawPage, Reference< XOutputStream > &xOutputStream, sal_uInt16 nPage, sal_Bool bExportObjects )
+{
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+ if( !xDrawPage.is() || !xPropSet.is() )
+ return sal_False;
+
+ if( NULL == mpWriter )
+ {
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Width") ) ) >>= mnDocWidth;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Height") ) ) >>= mnDocHeight;
+
+ mpWriter = new Writer( 14400, 10800, mnDocWidth, mnDocHeight, mnJPEGcompressMode );
+ }
+
+ sal_uInt16 ret = exportBackgrounds(xDrawPage, nPage, bExportObjects);
+
+ if (ret != nPage)
+ return ret;
+
+ if (bExportObjects)
+ mpWriter->placeShape( maPagesMap[nPage].mnObjectsID, _uInt16(1), 0, 0 );
+ else
+ mpWriter->placeShape( maPagesMap[nPage].mnBackgroundID, _uInt16(0), 0, 0 );
+
+ mpWriter->storeTo( xOutputStream );
+
+ return nPage;
+}
+
+sal_uInt16 FlashExporter::exportBackgrounds( Reference< XDrawPage > xDrawPage, sal_uInt16 nPage, sal_Bool bExportObjects )
+{
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+ if( !xDrawPage.is() || !xPropSet.is() )
+ return sal_False;
+
+ sal_Bool bBackgroundVisible, bBackgroundObjectsVisible;
+
+ try
+ {
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("IsBackgroundVisible") ) ) >>= bBackgroundVisible;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("IsBackgroundObjectsVisible") ) ) >>= bBackgroundObjectsVisible;
+ }
+ catch( exception& )
+ {
+ OSL_ASSERT( false );
+ }
+
+
+ if (bExportObjects)
+ {
+ if (bBackgroundObjectsVisible)
+ {
+ Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
+ if( !xMasterPageTarget.is() )
+ {
+ maPagesMap[nPage].mnObjectsID = -1;
+ return -1;
+ }
+
+ sal_uInt16 ret = exportMasterPageObjects(nPage, xMasterPageTarget->getMasterPage());
+ if (ret != nPage)
+ return ret;
+ }
+ else
+ {
+ maPagesMap[nPage].mnObjectsID = -1;
+ return -1;
+ }
+ }
+ else
+ {
+ if (bBackgroundVisible)
+ {
+ sal_uInt16 ret = exportDrawPageBackground(nPage, xDrawPage);
+
+ if (ret != nPage)
+ return ret;
+ }
+ else
+ {
+ maPagesMap[nPage].mnBackgroundID = -1;
+ return -1;
+ }
+ }
+
+ return nPage;
+}
+
+#ifdef AUGUSTUS
+sal_Bool FlashExporter::exportSound( Reference< XOutputStream > &xOutputStream, const char* wavfilename )
+{
+ try
+ {
+ delete mpWriter;
+ mpWriter = new Writer( 0, 0, 0, 0 );
+ }
+ catch( exception& )
+ {
+ OSL_ASSERT( false );
+ }
+
+ if (!mpWriter->streamSound(wavfilename))
+ return sal_False;
+ else
+ mpWriter->storeTo( xOutputStream );
+
+ return sal_True;
+}
+#endif // defined AUGUSTUS
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 nPlaceDepth;
+// AS: A Slide can have a private background or use its masterpage's background.
+// We use the checksums on the metafiles to tell if backgrounds are the same and
+// should be reused. The return value indicates which slide's background to use.
+// If the return value != nPage, then there is no background (if == -1) or the
+// background has already been exported.
+sal_uInt16 FlashExporter::exportDrawPageBackground(sal_uInt16 nPage, Reference< XDrawPage >& xPage)
+{
+ sal_uInt16 rBackgroundID;
+
+ GDIMetaFile aMtfPrivate, aMtfMaster;
+ Reference< XComponent > xComponent( xPage, UNO_QUERY );
+
+ Reference< XMasterPageTarget > xMasterPageTarget( xPage, UNO_QUERY );
+ if( !xMasterPageTarget.is() )
+ return -1;
+
+ Reference< XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
+ if( !xMasterPage.is())
+ return -1;
+
+ Reference< XComponent > xCompMaster( xMasterPage, UNO_QUERY );
+
+ getMetaFile( xCompMaster, aMtfMaster, true );
+ getMetaFile( xComponent, aMtfPrivate, true );
+
+ sal_uInt32 masterchecksum = aMtfMaster.GetChecksum();
+ sal_uInt32 privatechecksum = aMtfPrivate.GetChecksum();
+
+ // AS: If the slide has its own background
+ if (privatechecksum)
+ {
+ ChecksumCache::iterator it = gPrivateCache.find(privatechecksum);
+
+ // AS: and we've previously encountered this background, just return
+ // the previous index.
+ if (gPrivateCache.end() != it)
+ {
+ maPagesMap[nPage].mnBackgroundID =
+ maPagesMap[it->second].mnBackgroundID;
+ return it->second;
+ }
+ else
+ {
+ // AS: Otherwise, cache this checksum.
+ gPrivateCache[privatechecksum] = nPage;
+
+ rBackgroundID = mpWriter->defineShape( aMtfPrivate );
+
+ mpWriter->placeShape( rBackgroundID, _uInt16(0), 0, 0 );
+
+ maPagesMap[nPage].mnBackgroundID = rBackgroundID;
+ return nPage;
+ }
+ }
+
+ // AS: Ok, no private background. Use the master page's.
+ // AS: Have we already exported this master page?
+ ChecksumCache::iterator it = gMasterCache.find(masterchecksum);
+
+ if (gMasterCache.end() != it)
+ {
+ maPagesMap[nPage].mnBackgroundID =
+ maPagesMap[it->second].mnBackgroundID;
+
+ return it->second; // AS: Yes, so don't export it again.
+ }
+
+ gMasterCache[masterchecksum] = nPage;
+
+ rBackgroundID = mpWriter->defineShape( aMtfMaster );
+
+ maPagesMap[nPage].mnBackgroundID = rBackgroundID;
+
+ return nPage;
+}
+
+sal_uInt16 FlashExporter::exportMasterPageObjects(sal_uInt16 nPage, Reference< XDrawPage >& xMasterPage)
+{
+ Reference< XShapes > xShapes( xMasterPage, UNO_QUERY );
+
+ sal_uInt32 shapesum = ActionSummer(xShapes);
+
+ ChecksumCache::iterator it = gObjectCache.find(shapesum);
+
+ if (gObjectCache.end() != it)
+ {
+ maPagesMap[nPage].mnObjectsID =
+ maPagesMap[it->second].mnObjectsID;
+
+ return it->second; // AS: Yes, so don't export it again.
+ }
+
+ gObjectCache[shapesum] = nPage;
+
+ sal_uInt16 rObjectsID = mpWriter->startSprite();
+ exportDrawPageContents( xMasterPage, sal_False );
+ mpWriter->endSprite();
+
+ maPagesMap[nPage].mnObjectsID = rObjectsID;
+
+ return nPage;
+}
+
+// -----------------------------------------------------------------------------
+
+/** export's the definition of the shapes inside this drawing page and adds the
+ shape infos to the current PageInfo */
+void FlashExporter::exportDrawPageContents( Reference< XDrawPage >& xPage, sal_Bool bStream )
+{
+ Reference< XShapes > xShapes( xPage, UNO_QUERY );
+ exportShapes(xShapes, bStream);
+}
+
+// -----------------------------------------------------------------------------
+
+/** export's the definition of the shapes inside this XShapes container and adds the
+ shape infos to the current PageInfo */
+void FlashExporter::exportShapes( Reference< XShapes >& xShapes, sal_Bool bStream)
+{
+ OSL_ENSURE( (xShapes->getCount() <= 0xffff), "overflow in FlashExporter::exportDrawPageContents()" );
+
+ sal_uInt16 nShapeCount = (sal_uInt16)min( xShapes->getCount(), (sal_Int32)0xffff );
+ sal_uInt16 nShape;
+
+ Reference< XShape > xShape;
+
+ for( nShape = 0; nShape < nShapeCount; nShape++ )
+ {
+ xShapes->getByIndex( nShape ) >>= xShape;
+
+ if( xShape.is() )
+ {
+ Reference< XShapes > xShapes( xShape, UNO_QUERY );
+ if( xShapes.is() && xShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.GroupShape")))
+ // export the contents of group shapes, but we only ever stream at the top
+ // recursive level anyway, so pass false for streaming.
+ exportShapes( xShapes, false);
+ else
+ exportShape( xShape);
+ }
+
+ if (bStream)
+ mpWriter->showFrame();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+/** export this shape definition and adds it's info to the current PageInfo */
+void FlashExporter::exportShape( Reference< XShape >& xShape)
+{
+ Reference< XPropertySet > xPropSet( xShape, UNO_QUERY );
+ if( !xPropSet.is() )
+ return;
+
+ try
+ {
+ // skip empty presentation objects
+ sal_Bool bEmpty;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("IsEmptyPresentationObject") ) ) >>= bEmpty;
+ if( bEmpty )
+ return;
+ }
+ catch( Exception& )
+ {
+ // TODO: If we are exporting a draw, this property is not available
+ }
+
+ try
+ {
+ com::sun::star::awt::Point aPosition( xShape->getPosition() );
+ com::sun::star::awt::Size aSize( xShape->getSize() );
+
+ com::sun::star::awt::Rectangle aBoundRect;//(aPosition.X, aPosition.Y, aSize.Width, aSize.Height);
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("BoundRect") ) ) >>= aBoundRect;
+
+ ShapeInfo* pShapeInfo = new ShapeInfo();
+ pShapeInfo->mnX = aBoundRect.X;
+ pShapeInfo->mnY = aBoundRect.Y;
+ pShapeInfo->mnWidth = aBoundRect.Width;
+ pShapeInfo->mnHeight = aBoundRect.Height;
+
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Bookmark") ) ) >>= pShapeInfo->maBookmark;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("DimColor") ) ) >>= pShapeInfo->mnDimColor;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("DimHide") ) ) >>= pShapeInfo->mbDimHide;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("DimPrevious") ) ) >>= pShapeInfo->mbDimPrev;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Effect") ) ) >>= pShapeInfo->meEffect;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("PlayFull") ) ) >>= pShapeInfo->mbPlayFull;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("PresentationOrder") ) ) >>= pShapeInfo->mnPresOrder;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Sound") ) ) >>= pShapeInfo->maSoundURL;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("SoundOn") ) ) >>= pShapeInfo->mbSoundOn;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Speed") ) ) >>= pShapeInfo->meEffectSpeed;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("TextEffect") ) ) >>= pShapeInfo->meTextEffect;
+ xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("TransparentColor") ) ) >>= pShapeInfo->mnBlueScreenColor;
+
+// long ZOrder;
+// xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("ZOrder") ) ) >>= ZOrder;
+
+ GDIMetaFile aMtf;
+ Reference< XComponent > xComponent( xShape, UNO_QUERY );
+
+ bool bIsOleObject = xShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.OLE2Shape"))
+ || xShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.OLE2Shape"));
+
+ getMetaFile( xComponent, aMtf );
+
+ // AS: If it's an OLE object, then export a JPEG if the user requested.
+ // In this case, we use the bounding rect info generated in the first getMetaFile
+ // call, and then clear the metafile and add a BMP action. This may be turned into
+ // a JPEG, depending on what gives the best compression.
+ if (bIsOleObject && mbExportOLEAsJPEG)
+ getMetaFile( xComponent, aMtf, false, true );
+
+ sal_uInt16 nID;
+ sal_uInt32 checksum = aMtf.GetChecksum();
+
+ ChecksumCache::iterator it = gMetafileCache.find(checksum);
+
+ if (gMetafileCache.end() != it)
+ nID = it->second;
+ else
+ {
+ nID = mpWriter->defineShape( aMtf );
+ gMetafileCache[checksum] = nID;
+ }
+
+ if (!nID)
+ return;
+
+ pShapeInfo->mnID = nID;
+
+// pPageInfo->addShape( pShapeInfo );
+
+ mpWriter->placeShape( pShapeInfo->mnID, _uInt16(nPlaceDepth++), pShapeInfo->mnX, pShapeInfo->mnY );
+
+ delete pShapeInfo;
+ }
+ catch( Exception& )
+ {
+ OSL_ASSERT(false);
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool FlashExporter::getMetaFile( Reference< XComponent >&xComponent, GDIMetaFile& rMtf, bool bOnlyBackground /* = false */, bool bExportAsJPEG /* = false */)
+{
+ if( !mxGraphicExporter.is() )
+ mxGraphicExporter = Reference< XExporter >::query( mxMSF->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.GraphicExportFilter") ) ) );
+
+ Reference< XFilter > xFilter( mxGraphicExporter, UNO_QUERY );
+
+ utl::TempFile aFile;
+ aFile.EnableKillingFile();
+
+ Sequence< PropertyValue > aFilterData( false && bExportAsJPEG ? 2 : 1);
+ aFilterData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("Version") );
+ aFilterData[0].Value <<= (sal_Int32)6000;
+
+ if (false && bExportAsJPEG)
+ {
+ aFilterData[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("Translucent") );
+ aFilterData[1].Value <<= (sal_Bool)sal_True;
+ }
+
+ Sequence< PropertyValue > aDescriptor( bOnlyBackground ? 4 : 3 );
+ aDescriptor[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("FilterName") );
+
+ // AS: If we've been asked to export as an image, then use the BMP filter.
+ // Otherwise, use SVM. This is useful for things that don't convert well as
+ // metafiles, like the occasional OLE object.
+ aDescriptor[0].Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM(bExportAsJPEG ? "PNG" : "SVM") );
+
+ aDescriptor[1].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("URL") );
+ aDescriptor[1].Value <<= OUString( aFile.GetURL() );
+ aDescriptor[2].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("FilterData") );
+ aDescriptor[2].Value <<= aFilterData;
+ if( bOnlyBackground )
+ {
+ aDescriptor[3].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("ExportOnlyBackground") );
+ aDescriptor[3].Value <<= (sal_Bool)bOnlyBackground;
+ }
+ mxGraphicExporter->setSourceDocument( xComponent );
+ xFilter->filter( aDescriptor );
+
+ if (bExportAsJPEG)
+ {
+ Graphic aGraphic;
+ GraphicFilter aFilter(false);
+
+ USHORT nRet = aFilter.ImportGraphic( aGraphic, String(aFile.GetURL()), *aFile.GetStream( STREAM_READ ) );
+ BitmapEx rBitmapEx( aGraphic.GetBitmap(), Color(255,255,255) );
+
+ sal_Bool bHasAlpha = rBitmapEx.IsAlpha();
+ sal_Bool bIsTransparent = rBitmapEx.IsTransparent();
+
+ Rectangle clipRect;
+ for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( i );
+ const USHORT nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
+ clipRect = pA->GetRect();
+ i = nCount;
+ break;
+ }
+ }
+ }
+ MetaBmpExScaleAction *pmetaAct = new MetaBmpExScaleAction(Point(clipRect.Left(), clipRect.Top()), Size(clipRect.GetWidth(), clipRect.GetHeight()), rBitmapEx);
+
+ rMtf.Clear();
+ rMtf.AddAction(pmetaAct);
+
+ }
+ else
+ rMtf.Read( *aFile.GetStream( STREAM_READ ) );
+
+ int icount = rMtf.GetActionCount();
+ return icount != 0;
+}
+
+sal_uInt32 FlashExporter::ActionSummer(Reference< XShape >& xShape)
+{
+ Reference< XShapes > xShapes( xShape, UNO_QUERY );
+
+ if( xShapes.is() )
+ {
+ return ActionSummer(xShapes);
+ }
+ else
+ {
+ Reference< XComponent > xComponentShape( xShape, UNO_QUERY );
+
+ GDIMetaFile aMtf;
+ getMetaFile( xComponentShape, aMtf);
+
+ return aMtf.GetChecksum();
+ }
+}
+
+sal_uInt32 FlashExporter::ActionSummer(Reference< XShapes >& xShapes)
+{
+ sal_uInt32 nShapeCount = xShapes->getCount();
+ sal_uInt32 shapecount = 0;
+
+ Reference< XShape > xShape2;
+
+ for( sal_uInt16 nShape = 0; nShape < nShapeCount; nShape++ )
+ {
+ xShapes->getByIndex( nShape ) >>= xShape2;
+
+ shapecount += ActionSummer(xShape2);
+ }
+
+ return shapecount;
+} \ No newline at end of file
diff --git a/filter/source/flash/swfexporter.hxx b/filter/source/flash/swfexporter.hxx
new file mode 100644
index 000000000000..068021dd9d15
--- /dev/null
+++ b/filter/source/flash/swfexporter.hxx
@@ -0,0 +1,270 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfexporter.hxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:02 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+#ifndef _FLASH_EXPORTER_HXX
+#define _FLASH_EXPORTER_HXX
+
+#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
+#include <com/sun/star/beans/XPropertySet.hpp>
+#endif
+#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
+#include <com/sun/star/lang/XComponent.hpp>
+#endif
+#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
+#include <com/sun/star/io/XOutputStream.hpp>
+#endif
+#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_
+#include <com/sun/star/document/XExporter.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#endif
+#ifndef _COM_SUN_STAR_PRESENTATION_ANIMATIONEFFECT_HPP_
+#include <com/sun/star/presentation/AnimationEffect.hpp>
+#endif
+#ifndef _COM_SUN_STAR_PRESENTATION_ANIMATIONSPEED_HPP_
+#include <com/sun/star/presentation/AnimationSpeed.hpp>
+#endif
+#ifndef _COM_SUN_STAR_PRESENTATION_CLICKACTION_HPP_
+#include <com/sun/star/presentation/ClickAction.hpp>
+#endif
+#ifndef _COM_SUN_STAR_PRESENTATION_FADEEFFECT_HPP_
+#include <com/sun/star/presentation/FadeEffect.hpp>
+#endif
+
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+
+#include <vector>
+#include <map>
+
+#include <stdio.h>
+
+typedef ::std::map<sal_uInt32, sal_uInt16> ChecksumCache;
+
+class GDIMetaFile;
+
+inline ::rtl::OUString STR(const sal_Char * in)
+{
+ return ::rtl::OUString::createFromAscii(in);
+}
+
+inline ::rtl::OUString VAL(sal_Int32 in)
+{
+ return ::rtl::OUString::valueOf(in);
+}
+
+namespace swf {
+
+class Writer;
+// -----------------------------------------------------------------------------
+
+class ShapeInfo
+{
+public:
+ sal_uInt16 mnID; // the character id for the sprite definition of this shape
+
+ sal_Int32 mnX;
+ sal_Int32 mnY;
+
+ sal_Int32 mnWidth;
+ sal_Int32 mnHeight;
+
+ ::com::sun::star::presentation::AnimationEffect meEffect;
+ ::com::sun::star::presentation::AnimationEffect meTextEffect;
+ ::com::sun::star::presentation::AnimationSpeed meEffectSpeed;
+
+ sal_Int32 mnPresOrder;
+
+ ::com::sun::star::presentation::ClickAction meClickAction;
+ ::rtl::OUString maBookmark;
+
+ sal_Int32 mnDimColor;
+ sal_Bool mbDimHide;
+ sal_Bool mbDimPrev;
+
+ sal_Bool mbSoundOn;
+ sal_Bool mbPlayFull;
+ ::rtl::OUString maSoundURL;
+
+ sal_Int32 mnBlueScreenColor;
+
+ ShapeInfo() :
+ mnID(0), mnX(0), mnY(0),
+ meEffect( ::com::sun::star::presentation::AnimationEffect_NONE ),
+ meTextEffect( ::com::sun::star::presentation::AnimationEffect_NONE ),
+ meEffectSpeed( ::com::sun::star::presentation::AnimationSpeed_MEDIUM ),
+ mnPresOrder( 0 ),
+ meClickAction( ::com::sun::star::presentation::ClickAction_NONE ),
+ mnDimColor( 0 ),
+ mbDimHide( false ),
+ mbDimPrev( false ),
+ mbSoundOn( false ),
+ mbPlayFull( false ),
+ mnBlueScreenColor( 0 ) {}
+};
+
+typedef ::std::vector<ShapeInfo*> ShapeInfoVector;
+
+// -----------------------------------------------------------------------------
+
+struct ShapeAnimationInfo
+{
+ ShapeInfo* mpShapeInfo;
+ sal_uInt16 mnDepth;
+
+ ShapeAnimationInfo( ShapeInfo* pShapeInfo, sal_uInt16 nDepth ) : mpShapeInfo( pShapeInfo ), mnDepth( nDepth ) {}
+};
+
+typedef std::vector<ShapeAnimationInfo> ShapeAnimationInfoVector;
+
+// -----------------------------------------------------------------------------
+
+struct PageInfo
+{
+ sal_uInt16 mnBackgroundID;
+ sal_uInt16 mnObjectsID;
+ sal_uInt16 mnForegroundID;
+
+ sal_Int32 mnChange;
+
+ ::com::sun::star::presentation::FadeEffect meFadeEffect;
+ ::com::sun::star::presentation::AnimationSpeed meFadeSpeed;
+
+ sal_Int32 mnDuration;
+
+ sal_Bool mbBackgroundVisible;
+ sal_Bool mbBackgroundObjectsVisible;
+
+ ShapeInfoVector maShapesVector;
+
+ PageInfo();
+ ~PageInfo();
+
+ void addShape( ShapeInfo* pShapeInfo );
+
+};
+
+// -----------------------------------------------------------------------------
+
+typedef ::std::map<sal_uInt32, PageInfo> PageInfoMap;
+
+// -----------------------------------------------------------------------------
+
+class FlashExporter
+{
+public:
+ FlashExporter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF, sal_Int32 nJPEGCompressMode = -1, sal_Bool bExportOLEAsJPEG = false);
+ ~FlashExporter();
+
+ void Flush();
+
+ sal_Bool exportAll( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xDoc, com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > &xOutputStream, ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator> &xStatusIndicator );
+ sal_Bool exportSlides( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > xDrawPage, com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > &xOutputStream, sal_uInt16 nPage);
+ sal_uInt16 exportBackgrounds( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > xDrawPage, com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > &xOutputStream, sal_uInt16 nPage, sal_Bool bExportObjects );
+ sal_uInt16 exportBackgrounds( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > xDrawPage, sal_uInt16 nPage, sal_Bool bExportObjects );
+
+#ifdef AUGUSTUS
+ sal_Bool exportSound( com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > &xOutputStream, const char* wavfilename );
+#endif
+
+ ChecksumCache gMasterCache;
+ ChecksumCache gPrivateCache;
+ ChecksumCache gObjectCache;
+ ChecksumCache gMetafileCache;
+
+private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF;
+ ::com::sun::star::uno::Reference< ::com::sun::star::document::XExporter > mxGraphicExporter;
+
+ PageInfoMap maPagesMap;
+
+ sal_uInt16 exportDrawPageBackground(sal_uInt16 nPage, ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xPage);
+ sal_uInt16 exportMasterPageObjects(sal_uInt16 nPage, ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xMasterPage);
+
+ void exportDrawPageContents( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xPage, sal_Bool bStream );
+ void exportShapes( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xShapes, sal_Bool bStream );
+ void exportShape( ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape);
+
+ sal_uInt32 ActionSummer(::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape);
+ sal_uInt32 ActionSummer(::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xShapes);
+
+ void animateShape( ShapeAnimationInfo& rAnimInfo );
+ void animatePage( PageInfo* pPageInfo );
+
+ bool getMetaFile( ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >&xComponent, GDIMetaFile& rMtf, bool bOnlyBackground = false, bool bExportAsJPEG = false );
+
+ Writer* mpWriter;
+
+ sal_Int32 mnDocWidth;
+ sal_Int32 mnDocHeight;
+
+ sal_Int32 mnJPEGcompressMode;
+
+ sal_Bool mbExportOLEAsJPEG;
+};
+
+}
+
+#endif
diff --git a/filter/source/flash/swffilter.cxx b/filter/source/flash/swffilter.cxx
new file mode 100644
index 000000000000..61fcfc757aa9
--- /dev/null
+++ b/filter/source/flash/swffilter.cxx
@@ -0,0 +1,601 @@
+/*************************************************************************
+ *
+ * $RCSfile: swffilter.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:02 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
+#include <com/sun/star/frame/XDesktop.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XSTORABLE_HPP_
+#include <com/sun/star/frame/XStorable.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DOCUMENT_XFILTER_HPP_
+#include <com/sun/star/document/XFilter.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DOCUMENT_XEXPORTER_HPP_
+#include <com/sun/star/document/XExporter.hpp>
+#endif
+#ifndef _COM_SUN_STAR_LANG_XINITIALIZATION_HPP_
+#include <com/sun/star/lang/XInitialization.hpp>
+#endif
+#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESSUPPLIER_HPP_
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#endif
+#ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_
+#include <com/sun/star/drawing/XDrawView.hpp>
+#endif
+#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
+#include <com/sun/star/container/XIndexAccess.hpp>
+#endif
+#ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_
+#include <com/sun/star/frame/XModel.hpp>
+#endif
+#ifndef _COM_SUN_STAR_TASK_XSTATUSINDICATORFACTORY_HPP_
+#include <com/sun/star/task/XStatusIndicatorFactory.hpp>
+#endif
+#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
+#include <com/sun/star/io/XOutputStream.hpp>
+#endif
+#ifndef _CPPUHELPER_IMPLBASE1_HXX_
+#include <cppuhelper/implbase1.hxx>
+#endif
+
+#ifndef _CPPUHELPER_IMPLBASE4_HXX_
+#include <cppuhelper/implbase4.hxx>
+#endif
+
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+
+#include "swfexporter.hxx"
+
+//#include <stdlib.h>
+//#include <windows.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::frame;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::presentation;
+using namespace ::com::sun::star::task;
+
+using ::rtl::OUString;
+using ::rtl::OString;
+using ::com::sun::star::lang::XComponent;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::io::XOutputStream;
+using ::com::sun::star::container::XIndexAccess;
+using ::osl::FileBase;
+using ::com::sun::star::frame::XModel;
+
+namespace swf {
+
+typedef ::cppu::WeakImplHelper1<com::sun::star::io::XOutputStream> OslOutputStreamWrapper_Base;
+ // needed for some compilers
+class OslOutputStreamWrapper : public OslOutputStreamWrapper_Base
+{
+ osl::File mrFile;
+
+public:
+ OslOutputStreamWrapper(const OUString& sFileName) : mrFile(sFileName)
+ {
+ osl_removeFile(sFileName.pData);
+ mrFile.open(OpenFlag_Create|OpenFlag_Write);
+ }
+
+ // stario::XOutputStream
+ virtual void SAL_CALL writeBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL flush( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL closeOutput( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+};
+
+void SAL_CALL OslOutputStreamWrapper::writeBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& aData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
+{
+ sal_uInt64 uBytesToWrite = aData.getLength();
+ sal_uInt64 uBytesWritten = 0;
+
+ sal_Int8 const * pBuffer = aData.getConstArray();
+
+ while( uBytesToWrite )
+ {
+ osl::File::RC eRC = mrFile.write( pBuffer, uBytesToWrite, uBytesWritten);
+
+ switch( eRC )
+ {
+ case osl::File::E_INVAL: // the format of the parameters was not valid
+ case osl::File::E_FBIG: // File too large
+
+ case osl::File::E_AGAIN: // Operation would block
+ case osl::File::E_BADF: // Bad file
+ case osl::File::E_FAULT: // Bad address
+ case osl::File::E_INTR: // function call was interrupted
+ case osl::File::E_IO: // I/O error
+ case osl::File::E_NOLCK: // No record locks available
+ case osl::File::E_NOLINK: // Link has been severed
+ case osl::File::E_NOSPC: // No space left on device
+ case osl::File::E_NXIO: // No such device or address
+ throw com::sun::star::io::IOException(); // TODO: Better error handling
+ }
+
+ uBytesToWrite -= uBytesWritten;
+ pBuffer += uBytesWritten;
+ }
+}
+
+void SAL_CALL OslOutputStreamWrapper::flush( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
+{
+}
+
+void SAL_CALL OslOutputStreamWrapper::closeOutput( ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
+{
+ osl::File::RC eRC = mrFile.close();
+
+ switch( eRC )
+ {
+ case osl::File::E_INVAL: // the format of the parameters was not valid
+
+ case osl::File::E_BADF: // Bad file
+ case osl::File::E_INTR: // function call was interrupted
+ case osl::File::E_NOLINK: // Link has been severed
+ case osl::File::E_NOSPC: // No space left on device
+ case osl::File::E_IO: // I/O error
+ throw com::sun::star::io::IOException(); // TODO: Better error handling
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+class FlashExportFilter : public cppu::WeakImplHelper4
+<
+ com::sun::star::document::XFilter,
+ com::sun::star::document::XExporter,
+ com::sun::star::lang::XInitialization,
+ com::sun::star::lang::XServiceInfo
+>
+{
+ Reference< XComponent > mxDoc;
+ Reference< XMultiServiceFactory > mxMSF;
+ Reference< XStatusIndicator> mxStatusIndicator;
+
+ osl::File* mpFile;
+
+public:
+ FlashExportFilter( const Reference< XMultiServiceFactory > &rxMSF);
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) throw(RuntimeException);
+
+ sal_Bool ExportAsMultipleFiles( const Sequence< PropertyValue >& aDescriptor );
+ sal_Bool ExportAsSingleFile( const Sequence< PropertyValue >& aDescriptor );
+
+ virtual void SAL_CALL cancel( ) throw (RuntimeException);
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) throw(IllegalArgumentException, RuntimeException);
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw(Exception, RuntimeException);
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() throw(RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(RuntimeException);
+};
+
+// -----------------------------------------------------------------------------
+
+FlashExportFilter::FlashExportFilter(const Reference< XMultiServiceFactory > &rxMSF)
+: mxMSF( rxMSF )
+{
+}
+
+
+// -----------------------------------------------------------------------------
+
+OUString exportBackground(FlashExporter &aFlashExporter, Reference< XDrawPage > xDrawPage, OUString sPath, sal_uInt32 nPage, const char* suffix)
+{
+ OUString filename = STR("slide") + VAL(nPage+1) + STR(suffix) + STR(".swf");
+ OUString fullpath = sPath + STR("/") + filename;
+
+ // AS: If suffix is "o" then the last paramter is true (for exporting objects).
+ Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
+ sal_uInt32 nCached = aFlashExporter.exportBackgrounds( xDrawPage, xOutputStreamWrap, nPage, *suffix == 'o' );
+ aFlashExporter.Flush();
+ xOutputStreamWrap.clear();
+
+ if (nCached != nPage)
+ {
+ osl_removeFile(fullpath.pData);
+ if (-1 == nCached)
+ return STR("NULL");
+ else
+ return STR("slide") + VAL(nCached+1) + STR(suffix) + STR(".swf");
+ }
+
+ return filename;
+}
+
+template <typename TYPE>
+TYPE findPropertyValue(const Sequence< PropertyValue >& aPropertySequence, const sal_Char* name, TYPE def)
+{
+ TYPE temp;
+
+ sal_Int32 nLength = aPropertySequence.getLength();
+ const PropertyValue * pValue = aPropertySequence.getConstArray();
+
+ for ( sal_Int32 i = 0 ; i < nLength; i++)
+ {
+ if ( pValue[i].Name.equalsAsciiL ( name, strlen(name) ) )
+ {
+ pValue[i].Value >>= temp;
+ return temp;
+ }
+ }
+
+ return def;
+}
+
+sal_Bool SAL_CALL FlashExportFilter::filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
+ throw (RuntimeException)
+{
+ Sequence< PropertyValue > aFilterData;
+
+ aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData);
+
+ if (findPropertyValue<sal_Bool>(aFilterData, "ExportMultipleFiles", false ))
+ {
+ ExportAsMultipleFiles(aDescriptor);
+ }
+ else
+ {
+ ExportAsSingleFile(aDescriptor);
+ }
+
+ if( mxStatusIndicator.is() )
+ mxStatusIndicator->end();
+
+ return sal_True;
+}
+
+
+// AS: When exporting as multiple files, each background, object layer, and slide gets its own
+// file. Additionally, a file called BackgroundConfig.txt is generated, indicating which
+// background and objects (if any) go with each slide. The files are named slideNb.swf,
+// slideNo.swf, and slideNp.swf, where N is the slide number, and b=background, o=objects, and
+// p=slide contents. Note that under normal circumstances, there will be very few b and o files.
+
+// AS: HACK! Right now, I create a directory as a sibling to the swf file selected in the Export
+// dialog. This directory is called presentation.sxi-swf-files. The name of the swf file selected
+// in the Export dialog has no impact on this. All files created are placed in this directory.
+sal_Bool FlashExportFilter::ExportAsMultipleFiles(const Sequence< PropertyValue >& aDescriptor)
+{
+ Reference< XDrawPagesSupplier > xDrawPagesSupplier(mxDoc, UNO_QUERY);
+ if(!xDrawPagesSupplier.is())
+ return sal_False;
+
+ Reference< XIndexAccess > xDrawPages( xDrawPagesSupplier->getDrawPages(), UNO_QUERY );
+ if(!xDrawPages.is())
+ return sal_False;
+
+ Reference< XDesktop > rDesktop( mxMSF->createInstance(OUString::createFromAscii("com.sun.star.frame.Desktop")), UNO_QUERY);
+ if (!rDesktop.is())
+ return sal_False;
+
+ Reference< XStorable > xStorable(rDesktop->getCurrentComponent(), UNO_QUERY);
+ if (!xStorable.is())
+ return sal_False;
+
+ Reference< XDrawPage > xDrawPage;
+
+ Reference< XFrame > rFrame = rDesktop->getCurrentFrame();
+ Reference< XDrawView > rDrawView = Reference< XDrawView >( rFrame->getController(), UNO_QUERY );
+
+ Reference< XDrawPage > rCurrentPage = rDrawView->getCurrentPage();
+
+ Sequence< PropertyValue > aFilterData;
+
+ aFilterData = findPropertyValue<Sequence< PropertyValue > >(aDescriptor, "FilterData", aFilterData);
+
+ //AS: Do a bunch of path mangling to figure out where to put the files.
+
+ OUString sOriginalPath = findPropertyValue<OUString>(aDescriptor, "URL", OUString());
+
+ // AS: sPath is the parent directory, where everything else exists (like the sxi,
+ // the -swf-files folder, the -audio files, etc.
+ int lastslash = sOriginalPath.lastIndexOf('/');
+ OUString sPath( sOriginalPath.copy(0, lastslash) );
+
+ OUString sPresentation(xStorable->getLocation());
+
+ lastslash = sPresentation.lastIndexOf('/') + 1;
+ int lastdot = sPresentation.lastIndexOf('.');
+
+ // AS: The name of the presentation, without 3 character extension.
+ OUString sPresentationName = sPresentation.copy(lastslash, lastdot - lastslash);
+
+ OUString fullpath, swfdirpath, backgroundfilename, objectsfilename;
+
+ swfdirpath = sPath + STR("/") + sPresentationName + STR(".sxi-swf-files");
+
+ oslFileError err;
+ err = osl_createDirectory( swfdirpath.pData );
+
+ fullpath = swfdirpath + STR("/backgroundconfig.txt");
+
+ oslFileHandle xBackgroundConfig;
+
+ // AS: Only export the background config if we're exporting all of the pages, otherwise we'll
+ // screw it up.
+ sal_Bool bExportAll = findPropertyValue<sal_Bool>(aFilterData, "ExportAll", true);
+ if (bExportAll)
+ {
+ osl_removeFile(fullpath.pData);
+ osl_openFile( fullpath.pData, &xBackgroundConfig, osl_File_OpenFlag_Create | osl_File_OpenFlag_Write );
+
+ sal_uInt64 bytesWritten;
+ err = osl_writeFile(xBackgroundConfig, "slides=", strlen("slides="), &bytesWritten);
+ }
+
+ FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75),
+ findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false));
+
+ const sal_Int32 nPageCount = xDrawPages->getCount();
+ mxStatusIndicator->start(OUString( RTL_CONSTASCII_USTRINGPARAM( "Saving :" )), nPageCount);
+
+ for(sal_Int32 nPage = 0; nPage < nPageCount; nPage++)
+ {
+ mxStatusIndicator->setValue( nPage );
+ xDrawPages->getByIndex(nPage) >>= xDrawPage;
+
+ // AS: If we're only exporting the current page, then skip the rest.
+ if (!bExportAll && xDrawPage != rCurrentPage)
+ continue;
+
+ // AS: Export the background, the background objects, and then the slide contents.
+ if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgrounds", true))
+ {
+ backgroundfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "b");
+ }
+
+ if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportBackgroundObjects", true))
+ {
+ objectsfilename = exportBackground(aFlashExporter, xDrawPage, swfdirpath, nPage, "o");
+ }
+
+ if (bExportAll || findPropertyValue<sal_Bool>(aFilterData, "ExportSlideContents", true))
+ {
+ fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("p.swf");
+
+ Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
+ sal_Bool ret = aFlashExporter.exportSlides( xDrawPage, xOutputStreamWrap, nPage );
+ aFlashExporter.Flush();
+ xOutputStreamWrap.clear();
+
+ if (!ret)
+ osl_removeFile(fullpath.pData);
+ }
+
+ // AS: Write out to the background config what backgrounds and objects this
+ // slide used.
+ if (bExportAll)
+ {
+ OUString temp = backgroundfilename + STR("|") + objectsfilename;
+ OString ASCIItemp(temp.getStr(), temp.getLength(), RTL_TEXTENCODING_ASCII_US);
+
+ sal_uInt64 bytesWritten;
+ osl_writeFile(xBackgroundConfig, ASCIItemp.getStr(), ASCIItemp.getLength(), &bytesWritten);
+
+ if (nPage < nPageCount - 1)
+ osl_writeFile(xBackgroundConfig, "|", 1, &bytesWritten);
+ }
+
+#ifdef AUGUSTUS
+ if (findPropertyValue<sal_Bool>(aFilterData, "ExportSound", true))
+ {
+ fullpath = swfdirpath + STR("/slide") + VAL(nPage+1) + STR("s.swf");
+
+ OUString wavpath = sPath + STR("/") + sPresentationName + STR(".ppt-audio/slide") + VAL(nPage+1) + STR(".wav");
+ FileBase::getSystemPathFromFileURL(wavpath, wavpath);
+ OString sASCIIPath(wavpath.getStr(), wavpath.getLength(), RTL_TEXTENCODING_ASCII_US);
+
+ Reference<XOutputStream> xOutputStreamWrap(*(new OslOutputStreamWrapper(fullpath)), UNO_QUERY);
+ sal_Bool ret = aFlashExporter.exportSound(xOutputStreamWrap, sASCIIPath.getStr());
+ aFlashExporter.Flush();
+ xOutputStreamWrap.clear();
+
+ if (!ret)
+ osl_removeFile(fullpath.pData);
+ }
+#endif // defined AUGUSTUS
+ }
+
+ if (bExportAll)
+ osl_closeFile(xBackgroundConfig);
+
+ return sal_True;
+}
+
+sal_Bool FlashExportFilter::ExportAsSingleFile(const Sequence< PropertyValue >& aDescriptor)
+{
+ Reference < XOutputStream > xOutputStream = findPropertyValue<Reference<XOutputStream> >(aDescriptor, "OutputStream", 0);
+ Sequence< PropertyValue > aFilterData;
+
+ if (!xOutputStream.is() )
+ {
+ OSL_ASSERT ( 0 );
+ return sal_False;
+ }
+
+ FlashExporter aFlashExporter( mxMSF, findPropertyValue<sal_Int32>(aFilterData, "CompressMode", 75),
+ findPropertyValue<sal_Bool>(aFilterData, "ExportOLEAsJPEG", false));
+
+ return aFlashExporter.exportAll( mxDoc, xOutputStream, mxStatusIndicator );
+}
+
+// -----------------------------------------------------------------------------
+
+void SAL_CALL FlashExportFilter::cancel( )
+ throw (RuntimeException)
+{
+}
+
+// -----------------------------------------------------------------------------
+
+// XExporter
+void SAL_CALL FlashExportFilter::setSourceDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
+ throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException)
+{
+ mxDoc = xDoc;
+
+ // create the status indicator
+ Reference< XModel > xModel( mxDoc, UNO_QUERY );
+ if( xModel.is() )
+ {
+ Reference< com::sun::star::frame::XController >xController(xModel->getCurrentController());
+ if(xController.is())
+ {
+ Reference < com::sun::star::frame::XFrame >xFrame(xController->getFrame());
+ if(xFrame.is())
+ {
+ Reference<com::sun::star::task::XStatusIndicatorFactory> xFactory(xFrame,UNO_QUERY);
+ if (xFactory.is())
+ mxStatusIndicator = xFactory->createStatusIndicator();
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+// XInitialization
+void SAL_CALL FlashExportFilter::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments )
+ throw (Exception, RuntimeException)
+{
+}
+
+// -----------------------------------------------------------------------------
+
+OUString FlashExportFilter_getImplementationName ()
+ throw (RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Impress.FlashExportFilter" ) );
+}
+
+// -----------------------------------------------------------------------------
+
+#define SERVICE_NAME "com.sun.star.document.ExportFilter"
+
+sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName )
+ throw (RuntimeException)
+{
+ return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
+}
+
+// -----------------------------------------------------------------------------
+
+Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames( )
+ throw (RuntimeException)
+{
+ Sequence < OUString > aRet(1);
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
+ return aRet;
+}
+#undef SERVICE_NAME
+
+// -----------------------------------------------------------------------------
+
+Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
+ throw( Exception )
+{
+ return (cppu::OWeakObject*) new FlashExportFilter( rSMgr );
+}
+
+// -----------------------------------------------------------------------------
+
+// XServiceInfo
+OUString SAL_CALL FlashExportFilter::getImplementationName( )
+ throw (RuntimeException)
+{
+ return FlashExportFilter_getImplementationName();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool SAL_CALL FlashExportFilter::supportsService( const OUString& rServiceName )
+ throw (RuntimeException)
+{
+ return FlashExportFilter_supportsService( rServiceName );
+}
+
+// -----------------------------------------------------------------------------
+
+::com::sun::star::uno::Sequence< OUString > SAL_CALL FlashExportFilter::getSupportedServiceNames( )
+ throw (RuntimeException)
+{
+ return FlashExportFilter_getSupportedServiceNames();
+}
+
+// -----------------------------------------------------------------------------
+
+}
diff --git a/filter/source/flash/swfuno.cxx b/filter/source/flash/swfuno.cxx
new file mode 100644
index 000000000000..e94418eee77a
--- /dev/null
+++ b/filter/source/flash/swfuno.cxx
@@ -0,0 +1,170 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfuno.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:03 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#include <stdio.h>
+
+#include <osl/mutex.hxx>
+#include <osl/thread.h>
+#include <cppuhelper/factory.hxx>
+
+#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#endif
+
+using namespace ::rtl;
+using namespace ::cppu;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+
+namespace swf {
+extern OUString FlashExportFilter_getImplementationName() throw ( RuntimeException );
+extern sal_Bool SAL_CALL FlashExportFilter_supportsService( const OUString& ServiceName ) throw ( RuntimeException );
+extern Sequence< OUString > SAL_CALL FlashExportFilter_getSupportedServiceNames() throw ( RuntimeException );
+extern Reference< XInterface > SAL_CALL FlashExportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) throw ( Exception );
+}
+
+extern rtl::OUString SWFDialog_getImplementationName () throw (com::sun::star::uno::RuntimeException);
+extern com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL SWFDialog_getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException);
+extern com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL SWFDialog_createInstance( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > & rSMgr) throw( com::sun::star::uno::Exception );
+
+using namespace ::swf;
+
+extern "C"
+{
+//==================================================================================================
+void SAL_CALL component_getImplementationEnvironment(
+ const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+//==================================================================================================
+
+void singlecomponent_writeInfo( Reference< XRegistryKey >& xNewKey, const Sequence< OUString > & rSNL )
+{
+ const OUString * pArray = rSNL.getConstArray();
+ for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
+ xNewKey->createKey( pArray[nPos] );
+}
+
+sal_Bool SAL_CALL component_writeInfo(
+ void * pServiceManager, void * pRegistryKey )
+{
+ if (pRegistryKey)
+ {
+ try
+ {
+ Reference< XRegistryKey > xNewKey(
+ reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( FlashExportFilter_getImplementationName() ) );
+ xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );
+
+ singlecomponent_writeInfo( xNewKey, FlashExportFilter_getSupportedServiceNames() );
+
+ xNewKey = reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( SWFDialog_getImplementationName() );
+ xNewKey = xNewKey->createKey( OUString::createFromAscii( "/UNO/SERVICES" ) );
+
+ singlecomponent_writeInfo( xNewKey, SWFDialog_getSupportedServiceNames() );
+
+ return sal_True;
+ }
+ catch (InvalidRegistryException &)
+ {
+ OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
+ }
+ }
+ return sal_False;
+}
+//==================================================================================================
+void * SAL_CALL component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
+{
+ void * pRet = 0;
+
+ if( pServiceManager )
+ {
+ Reference< XSingleServiceFactory > xFactory;
+
+ OUString implName = OUString::createFromAscii( pImplName );
+ if ( implName.equals(FlashExportFilter_getImplementationName()) )
+ {
+ xFactory = createSingleFactory(
+ reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
+ OUString::createFromAscii( pImplName ),
+ FlashExportFilter_createInstance, FlashExportFilter_getSupportedServiceNames() );
+
+ }
+ else if ( implName.equals(SWFDialog_getImplementationName()) )
+ {
+ xFactory = createSingleFactory(
+ reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
+ OUString::createFromAscii( pImplName ),
+ SWFDialog_createInstance, SWFDialog_getSupportedServiceNames() );
+ }
+
+ if (xFactory.is())
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ }
+
+ return pRet;
+}
+}
diff --git a/filter/source/flash/swfwriter.cxx b/filter/source/flash/swfwriter.cxx
new file mode 100644
index 000000000000..4afc13b0eba6
--- /dev/null
+++ b/filter/source/flash/swfwriter.cxx
@@ -0,0 +1,704 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfwriter.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:03 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SWF_WRITER_HXX_
+#include "swfwriter.hxx"
+#endif
+
+#ifndef _SV_VIRDEV_HXX
+#include <vcl/virdev.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <vcl/gdimtf.hxx>
+#endif
+
+using namespace ::swf;
+using namespace ::std;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+
+// -----------------------------------------------------------------------------
+
+static MapMode aTWIPSMode( MAP_TWIP );
+static MapMode a100thmmMode( MAP_100TH_MM );
+
+static sal_Int32 map100thmm( sal_Int32 n100thMM )
+{
+ Point aPoint( n100thMM, n100thMM );
+ sal_Int32 nX = OutputDevice::LogicToLogic( aPoint, a100thmmMode, aTWIPSMode ).X();
+ return nX;
+}
+
+// -----------------------------------------------------------------------------
+
+Writer::Writer( sal_Int32 nTWIPWidthOutput, sal_Int32 nTWIPHeightOutput, sal_Int32 nDocWidthInput, sal_Int32 nDocHeightInput, sal_Int32 nJPEGcompressMode )
+: mpClipPolyPolygon( NULL ),
+ mpSprite( NULL ),
+ mpTag( NULL ),
+ mnNextId( 1 ),
+ mnJPEGCompressMode(nJPEGcompressMode),
+ mbWrittenJPEGTables(false),
+ mnGlobalTransparency(0)
+{
+ mpVDev = new VirtualDevice;
+ mpVDev->EnableOutput( sal_False );
+
+ maMovieTempFile.EnableKillingFile();
+ maFontsTempFile.EnableKillingFile();
+
+ mpMovieStream = maMovieTempFile.GetStream( STREAM_WRITE|STREAM_TRUNC );
+ mpFontsStream = maFontsTempFile.GetStream( STREAM_WRITE|STREAM_TRUNC );
+
+ mnFrames = 0;
+
+ mnDocWidth = map100thmm( nDocWidthInput );
+ mnDocHeight = map100thmm( nDocHeightInput );
+
+ mnDocXScale = (double)nTWIPWidthOutput / mnDocWidth;
+ mnDocYScale = (double)nTWIPHeightOutput / mnDocHeight;
+
+#ifndef AUGUSTUS
+ // define an invisible button with the size of a page
+ Rectangle aRect( 0, 0, mnDocWidth * mnDocXScale, mnDocHeight * mnDocYScale );
+ Polygon aPoly( aRect );
+ FillStyle aFill( Color(COL_WHITE) );
+ mnWhiteBackgroundShapeId = defineShape( aPoly, aFill );
+
+ Matrix3D m;
+ mnPageButtonId = createID();
+ startTag( TAG_DEFINEBUTTON );
+ mpTag->addUI16( mnPageButtonId ); // character id for button
+
+ // button records
+ mpTag->addUI8( 0x08 ); // only hit state
+ mpTag->addUI16( mnWhiteBackgroundShapeId ); // shape id of background rectangle
+ mpTag->addUI16( 0 ); // depth for button DANGER!
+ mpTag->addMatrix( m ); // identity matrix
+ mpTag->addUI8( 0 ); // empty color transform
+
+// mpTag->addUI8( 0 ); // end of button records
+
+ // action records
+ mpTag->addUI8( 0x06 ); // ActionPlay
+ mpTag->addUI8( 0 ); // end of action records
+
+ endTag();
+
+ // place a shape that clips shapes depth 2-3 to document boundaries
+// placeShape( mnWhiteBackgroundShapeId, 1, 0, 0, 4 );
+#endif
+}
+
+// -----------------------------------------------------------------------------
+
+Writer::~Writer()
+{
+ delete mpVDev;
+ delete mpSprite;
+ delete mpTag;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplCopySvStreamToXOutputStream( SvStream& rIn, Reference< XOutputStream > &xOut )
+{
+ sal_uInt32 nBufferSize = 64*1024;
+
+ rIn.Seek( STREAM_SEEK_TO_END );
+ sal_uInt32 nSize = rIn.Tell();
+ rIn.Seek( STREAM_SEEK_TO_BEGIN );
+
+ Sequence< sal_Int8 > aBuffer( min( nBufferSize, nSize ) );
+
+ while( nSize )
+ {
+ if( nSize < nBufferSize )
+ {
+ nBufferSize = nSize;
+ aBuffer.realloc( nSize );
+ }
+
+ sal_uInt32 nRead = rIn.Read( aBuffer.getArray(), nBufferSize );
+ DBG_ASSERT( nRead == nBufferSize, "ImplCopySvStreamToXOutputStream failed!" );
+ xOut->writeBytes( aBuffer );
+
+ nSize -= nBufferSize;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::storeTo( Reference< XOutputStream > &xOutStream )
+{
+ for(FontMap::iterator i = maFonts.begin(); i != maFonts.end(); i++)
+ {
+ FlashFont* pFont = (*i);
+ pFont->write( *mpFontsStream );
+ delete pFont;
+ }
+
+ // Endtag
+ *mpMovieStream << (sal_uInt8)0;
+
+ Tag aHeader( 0xff );
+
+ aHeader.addUI8( 'F' );
+ aHeader.addUI8( 'W' );
+ aHeader.addUI8( 'S' );
+ aHeader.addUI8( 5 );
+
+ sal_uInt32 nSizePos = aHeader.Tell();
+
+ aHeader << (sal_uInt32)0;
+
+ Rectangle aDocRect( 0, 0, static_cast<long>(mnDocWidth*mnDocXScale), static_cast<long>(mnDocHeight*mnDocYScale) );
+
+ aHeader.addRect( aDocRect );
+
+ // frame delay in 8.8 fixed number of frames per second
+ aHeader.addUI8( 0 );
+ aHeader.addUI8( 12 );
+
+ aHeader.addUI16( _uInt16(mnFrames) );
+
+ const sal_uInt32 nSize = aHeader.Tell() + mpFontsStream->Tell() + mpMovieStream->Tell();
+
+ aHeader.Seek( nSizePos );
+ aHeader << (sal_uInt32)nSize;
+
+ ImplCopySvStreamToXOutputStream( aHeader, xOutStream );
+ ImplCopySvStreamToXOutputStream( *mpFontsStream, xOutStream );
+ ImplCopySvStreamToXOutputStream( *mpMovieStream, xOutStream );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::startSprite()
+{
+ sal_uInt16 nShapeId = createID();
+ mvSpriteStack.push(mpSprite);
+ mpSprite = new Sprite( nShapeId );
+ return nShapeId;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::endSprite()
+{
+ if( mpSprite )
+ {
+ startTag( TAG_END );
+ endTag();
+
+ mpSprite->write( *mpMovieStream );
+ delete mpSprite;
+
+ if (mvSpriteStack.size() > 0)
+ {
+ mpSprite = mvSpriteStack.top();
+ mvSpriteStack.pop();
+ }
+ else
+ mpSprite = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::placeShape( sal_uInt16 nID, sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y, sal_uInt16 nClip, const char* pName )
+{
+ startTag( TAG_PLACEOBJECT2 );
+
+ BitStream aBits;
+
+ aBits.writeUB( nClip != 0, 1 ); // Has Clip Actions?
+ aBits.writeUB( 0, 1 ); // reserved
+ aBits.writeUB( pName != NULL, 1 ); // has a name
+ aBits.writeUB( 0, 1 ); // no ratio
+ aBits.writeUB( 0, 1 ); // no color transform
+ aBits.writeUB( 1, 1 ); // has a matrix
+ aBits.writeUB( 1, 1 ); // places a character
+ aBits.writeUB( 0, 1 ); // does not define a character to be moved
+
+ mpTag->addBits( aBits );
+ mpTag->addUI16( nDepth ); // depth
+ mpTag->addUI16( nID ); // character Id
+
+ Matrix3D aMatrix;
+ aMatrix.Translate( _Int16(static_cast<long>(map100thmm(x)*mnDocXScale)), _Int16(static_cast<long>(map100thmm(y)*mnDocYScale)) );
+ mpTag->addMatrix( aMatrix ); // transformation matrix
+
+ if( pName )
+ mpTag->addString( pName );
+
+ if( nClip != 0 )
+ mpTag->addUI16( nClip );
+
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::moveShape( sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y )
+{
+ startTag( TAG_PLACEOBJECT2 );
+
+ BitStream aBits;
+ aBits.writeUB( 0, 1 ); // Has no Clip Actions
+ aBits.writeUB( 0, 1 ); // reserved
+ aBits.writeUB( 0, 1 ); // has no name
+ aBits.writeUB( 0, 1 ); // no ratio
+ aBits.writeUB( 0, 1 ); // no color transform
+ aBits.writeUB( 1, 1 ); // has a matrix
+ aBits.writeUB( 0, 1 ); // places a character
+ aBits.writeUB( 1, 1 ); // defines a character to be moved
+
+ mpTag->addBits( aBits );
+ mpTag->addUI16( nDepth ); // depth
+
+ Matrix3D aMatrix;
+ aMatrix.Translate( _Int16(static_cast<long>(map100thmm(x)*mnDocXScale)), _Int16(static_cast<long>(map100thmm(y)*mnDocYScale)) );
+ mpTag->addMatrix( aMatrix ); // transformation matrix
+
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::removeShape( sal_uInt16 nDepth )
+{
+ startTag( TAG_REMOVEOBJECT2 );
+ mpTag->addUI16( nDepth ); // depth
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::setBackgroundColor( Color& rColor )
+{
+ startTag( TAG_BACKGROUNDCOLOR );
+ mpTag->addRGBA( rColor );
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::startTag( sal_uInt8 nTagId )
+{
+ DBG_ASSERT( mpTag == NULL, "Last tag was not ended");
+
+ mpTag = new Tag( nTagId );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::endTag()
+{
+ sal_uInt8 nTag = mpTag->getTagId();
+
+ if( mpSprite && ( (nTag == TAG_END) || (nTag == TAG_SHOWFRAME) || (nTag == TAG_DOACTION) || (nTag == TAG_STARTSOUND) || (nTag == TAG_PLACEOBJECT) || (nTag == TAG_PLACEOBJECT2) || (nTag == TAG_REMOVEOBJECT2) || (nTag == TAG_FRAMELABEL) ) )
+ {
+ mpSprite->addTag( mpTag );
+ mpTag = NULL;
+ }
+ else
+ {
+ mpTag->write( *mpMovieStream );
+ delete mpTag;
+ mpTag = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::createID()
+{
+ return mnNextId++;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::showFrame()
+{
+ startTag( TAG_SHOWFRAME );
+ endTag();
+
+ if(NULL == mpSprite)
+ mnFrames++;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::defineShape( const GDIMetaFile& rMtf, sal_Int16 x, sal_Int16 y )
+{
+ mpVDev->SetMapMode( rMtf.GetPrefMapMode() );
+ Impl_writeActions( rMtf );
+
+ sal_uInt16 nId = 0;
+ sal_uInt16 iDepth = 1;
+ {
+ CharacterIdVector::iterator aIter( maShapeIds.begin() );
+ const CharacterIdVector::iterator aEnd( maShapeIds.end() );
+
+ sal_Bool bHaveShapes = aIter != aEnd;
+
+ if (bHaveShapes)
+ {
+ nId = startSprite();
+
+ while( aIter != aEnd )
+ {
+ placeShape( *aIter, iDepth++, x, y );
+ aIter++;
+ }
+
+ endSprite();
+ }
+ }
+
+ maShapeIds.clear();
+
+ return nId;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::defineShape( const Polygon& rPoly, const FillStyle& rFillStyle )
+{
+ const PolyPolygon aPolyPoly( rPoly );
+ return defineShape( aPolyPoly, rFillStyle );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::defineShape( const Polygon& rPoly, sal_uInt16 nLineWidth, const Color& rLineColor )
+{
+ const PolyPolygon aPolyPoly( rPoly );
+ return defineShape( aPolyPoly, nLineWidth, rLineColor );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::defineShape( const PolyPolygon& rPolyPoly, const FillStyle& rFillStyle )
+{
+ sal_uInt16 nShapeId = createID();
+
+ // start a DefineShape3 tag
+ startTag( TAG_DEFINESHAPE3 );
+
+ mpTag->addUI16( nShapeId );
+ mpTag->addRect( rPolyPoly.GetBoundRect() );
+
+
+ // FILLSTYLEARRAY
+ mpTag->addUI8( 1 ); // FillStyleCount
+
+ // FILLSTYLE
+ rFillStyle.addTo( mpTag );
+
+ // LINESTYLEARRAY
+ mpTag->addUI8( 0 ); // LineStyleCount
+
+ // Number of fill and line index bits to 1
+ mpTag->addUI8( 0x11 );
+
+ BitStream aBits;
+
+ const sal_uInt16 nCount = rPolyPoly.Count();
+ sal_uInt16 i;
+ for( i = 0; i < nCount; i++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ i ];
+ if( rPoly.GetSize() )
+ Impl_addPolygon( aBits, rPoly, true );
+ }
+
+ Impl_addEndShapeRecord( aBits );
+
+ mpTag->addBits( aBits );
+ endTag();
+
+ return nShapeId;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::defineShape( const PolyPolygon& rPolyPoly, sal_uInt16 nLineWidth, const Color& rLineColor )
+{
+ sal_uInt16 nShapeId = createID();
+
+ // start a DefineShape3 tag
+ startTag( TAG_DEFINESHAPE3 );
+
+ mpTag->addUI16( nShapeId );
+ mpTag->addRect( rPolyPoly.GetBoundRect() );
+
+
+ // FILLSTYLEARRAY
+ mpTag->addUI8( 0 ); // FillStyleCount
+
+ // LINESTYLEARRAY
+ mpTag->addUI8( 1 ); // LineStyleCount
+
+ // LINESTYLE
+ mpTag->addUI16( nLineWidth ); // Width of line in twips
+ mpTag->addRGBA( rLineColor ); // Color
+
+ // Number of fill and line index bits to 1
+ mpTag->addUI8( 0x11 );
+
+ BitStream aBits;
+
+ const sal_uInt16 nCount = rPolyPoly.Count();
+ sal_uInt16 i;
+ for( i = 0; i < nCount; i++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ i ];
+ if( rPoly.GetSize() )
+ Impl_addPolygon( aBits, rPoly, false );
+ }
+
+ Impl_addEndShapeRecord( aBits );
+
+ mpTag->addBits( aBits );
+ endTag();
+
+ return nShapeId;
+}
+
+#ifdef AUGUSTUS
+enum {NO_COMPRESSION, ADPCM_COMPRESSION, MP3_COMPRESSION } COMPRESSION_TYPE;
+sal_Bool Writer::streamSound( const char * filename )
+{
+ SF_INFO info;
+ SNDFILE *sf = sf_open(filename, SFM_READ, &info);
+
+ if (NULL == sf)
+ return sal_False;
+ else
+ {
+ // AS: Start up lame.
+ m_lame_flags = lame_init();
+
+ // The default (if you set nothing) is a a J-Stereo, 44.1khz
+ // 128kbps CBR mp3 file at quality 5. Override various default settings
+ // as necessary, for example:
+
+ lame_set_num_channels(m_lame_flags,1);
+ lame_set_in_samplerate(m_lame_flags,22050);
+ lame_set_brate(m_lame_flags,48);
+ lame_set_mode(m_lame_flags,MONO);
+ lame_set_quality(m_lame_flags,2); /* 2=high 5 = medium 7=low */
+
+ // See lame.h for the complete list of options. Note that there are
+ // some lame_set_*() calls not documented in lame.h. These functions
+ // are experimental and for testing only. They may be removed in
+ // the future.
+
+ //4. Set more internal configuration based on data provided above,
+ // as well as checking for problems. Check that ret_code >= 0.
+
+ int ret_code = lame_init_params(m_lame_flags);
+
+ if (ret_code < 0)
+ throw 0;
+
+ int lame_frame_size = lame_get_framesize(m_lame_flags);
+ int samples_per_frame = 22050 / 12; // AS: (samples/sec) / (frames/sec) = samples/frame
+ int mp3buffer_size = static_cast<int>(samples_per_frame*1.25 + 7200 + 7200);
+
+
+ startTag(TAG_SOUNDSTREAMHEAD2);
+
+ mpTag->addUI8(2<<2 | 1<<1 | 0<<0); // Preferred mixer format ??
+
+ BitStream bs;
+
+ bs.writeUB(MP3_COMPRESSION,4);
+ bs.writeUB(2, 2); // AS: Reserved zero bits.
+ bs.writeUB(1, 1); // AS: 16 Bit
+ bs.writeUB(0, 1); // AS: Mono.
+
+ mpTag->addBits(bs);
+
+ mpTag->addUI16(samples_per_frame);
+ endTag();
+
+ short *sample_buff = new short[static_cast<int>(info.frames)];
+ sf_readf_short(sf, sample_buff, info.frames);
+
+ unsigned char* mp3buffer = new unsigned char[mp3buffer_size];
+
+// 5. Encode some data. input pcm data, output (maybe) mp3 frames.
+// This routine handles all buffering, resampling and filtering for you.
+// The required mp3buffer_size can be computed from num_samples,
+// samplerate and encoding rate, but here is a worst case estimate:
+// mp3buffer_size (in bytes) = 1.25*num_samples + 7200.
+// num_samples = the number of PCM samples in each channel. It is
+// not the sum of the number of samples in the L and R channels.
+//
+// The return code = number of bytes output in mp3buffer. This can be 0.
+// If it is <0, an error occured.
+
+
+ for (int samples_written = 0; samples_written < info.frames; samples_written += samples_per_frame)
+ {
+ startTag(TAG_SOUNDSTREAMBLOCK);
+
+ int samples_to_write = std::min((int)info.frames - samples_written, samples_per_frame);
+
+ // AS: Since we're mono, left and right sample buffs are the same
+ // ie, samplebuff (which is why we pass it twice).
+ int ret = lame_encode_buffer(m_lame_flags, sample_buff + samples_written,
+ sample_buff + samples_written,
+ samples_to_write, mp3buffer, mp3buffer_size);
+
+ if (ret < 0)
+ throw 0;
+
+// 6. lame_encode_flush will flush the buffers and may return a
+// final few mp3 frames. mp3buffer should be at least 7200 bytes.
+// return code = number of bytes output to mp3buffer. This can be 0.
+
+ if (mp3buffer_size - ret < 7200)
+ throw 0;
+
+ int ret2 = lame_encode_flush(m_lame_flags, mp3buffer + ret, mp3buffer_size - ret);
+
+ if (ret2 < 0)
+ throw 0;
+
+
+ SvMemoryStream strm(mp3buffer, ret + ret2, STREAM_READWRITE);
+
+ mpTag->addUI16(samples_to_write); //lame_frame_size);
+ mpTag->addUI16(0);
+ mpTag->addStream(strm);
+
+ endTag();
+
+ showFrame();
+ }
+
+
+ delete[] mp3buffer;
+
+ delete[] sample_buff;
+ int err = sf_close(sf);
+
+ // 8. free the internal data structures.
+ lame_close(m_lame_flags);
+ }
+
+ return sal_True;
+}
+#endif // AUGUSTUS
+
+
+// -----------------------------------------------------------------------------
+
+void Writer::stop()
+{
+ startTag( TAG_DOACTION );
+ mpTag->addUI8( 0x07 );
+ mpTag->addUI8( 0 );
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::play()
+{
+ startTag( TAG_DOACTION );
+ mpTag->addUI8( 0x06 );
+ mpTag->addUI8( 0 );
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::waitOnClick( sal_uInt16 nDepth )
+{
+ placeShape( _uInt16( mnPageButtonId ), nDepth, 0, 0 );
+ stop();
+ showFrame();
+ removeShape( nDepth );
+}
+
+// -----------------------------------------------------------------------------
+
+/** inserts a doaction tag with an ActionGotoFrame */
+void Writer::gotoFrame( sal_uInt16 nFrame )
+{
+ startTag( TAG_DOACTION );
+ mpTag->addUI8( 0x81 );
+ mpTag->addUI16( 2 );
+ mpTag->addUI16( nFrame );
+ mpTag->addUI8( 0 );
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 Writer::getWhiteBackgroundShapeId()
+{
+ return mnWhiteBackgroundShapeId;
+} \ No newline at end of file
diff --git a/filter/source/flash/swfwriter.hxx b/filter/source/flash/swfwriter.hxx
new file mode 100644
index 000000000000..3e72c72a69f3
--- /dev/null
+++ b/filter/source/flash/swfwriter.hxx
@@ -0,0 +1,522 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfwriter.hxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:03 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SWF_WRITER_HXX_
+#define _SWF_WRITER_HXX_
+
+#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
+#include <com/sun/star/uno/Sequence.hxx>
+#endif
+#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
+#include <com/sun/star/io/XOutputStream.hpp>
+#endif
+
+#ifndef _SV_FONT_HXX
+#include <vcl/font.hxx>
+#endif
+#ifndef _SV_GRADIENT_HXX
+#include <vcl/gradient.hxx>
+#endif
+#ifndef _UNOTOOLS_TEMPFILE_HXX
+#include <unotools/tempfile.hxx>
+#endif
+#ifndef _B2D_MATRIX3D_HXX
+#include <goodies/matrix3d.hxx>
+#endif
+#ifndef _TOOLS_COLOR_HXX
+#include <tools/color.hxx>
+#endif
+#ifndef _SV_POLY_HXX
+#include <vcl/poly.hxx>
+#endif
+#ifndef _SV_GEN_HXX
+#include <tools/gen.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+
+#include <vector>
+#include <stack>
+#include <map>
+
+#ifdef AUGUSTUS
+#include "lame.h"
+#include "sndfile.h"
+#endif
+
+#include <stdio.h>
+
+class GDIMetaFile;
+class BitmapEx;
+class PolyPolygon;
+class Gradient;
+class SvtGraphicFill;
+class SvtGraphicStroke;
+
+inline sal_uInt16 _uInt16( sal_Int32 nValue )
+{
+ OSL_ENSURE( (nValue >= 0) && ((sal_uInt32)nValue <= 0xffff), "overflow while converting sal_Int32 to sal_uInt16" );
+ return (sal_uInt16)nValue;
+}
+
+inline sal_Int16 _Int16( sal_Int32 nValue )
+{
+ OSL_ENSURE( (nValue >= -32768) && (nValue <= 32767), "overflow while converting sal_Int32 to sal_Int16" );
+ return (sal_Int16)nValue;
+}
+
+class VirtualDevice;
+
+namespace swf {
+
+const sal_uInt8 TAG_END = 0;
+const sal_uInt8 TAG_SHOWFRAME = 1;
+
+const sal_uInt8 TAG_DEFINEBUTTON = 7;
+
+const sal_uInt8 TAG_BACKGROUNDCOLOR = 9;
+
+const sal_uInt8 TAG_DOACTION = 12;
+const sal_uInt8 TAG_STARTSOUND = 15;
+
+const sal_uInt8 TAG_SOUNDSTREAMBLOCK = 19;
+const sal_uInt8 TAG_SOUNDSTREAMHEAD = 18;
+const sal_uInt8 TAG_SOUNDSTREAMHEAD2 = 45;
+
+const sal_uInt8 TAG_JPEGTABLES = 8;
+const sal_uInt8 TAG_DEFINEBITS = 6;
+const sal_uInt8 TAG_DEFINEBITSLOSSLESS = 20;
+const sal_uInt8 TAG_DEFINEBITSJPEG2 = 21;
+const sal_uInt8 TAG_DEFINEBITSJPEG3 = 35;
+const sal_uInt8 TAG_DEFINEBITSLOSSLESS2 = 36;
+
+const sal_uInt8 TAG_PLACEOBJECT = 4;
+const sal_uInt8 TAG_PLACEOBJECT2 = 26;
+const sal_uInt8 TAG_REMOVEOBJECT2 = 28;
+
+const sal_uInt8 TAG_DEFINEFONT = 10;
+const sal_uInt8 TAG_DEFINETEXT = 11;
+const sal_uInt8 TAG_DEFINESHAPE3 = 32;
+const sal_uInt8 TAG_DEFINESPRITE = 39;
+
+const sal_uInt8 TAG_FRAMELABEL = 43;
+
+const sal_uInt8 TAG_HEADER = 0xff;
+
+///////////////////////////////////////////////////////////////////////
+
+/** converts a double to a 16.16 flash fixed value */
+sal_uInt32 getFixed( double fValue );
+
+///////////////////////////////////////////////////////////////////////
+
+typedef ::std::map<sal_uInt32, sal_uInt16> ChecksumCache;
+
+/** unsigned int 16 compare operation for stl */
+struct ltuint16
+{
+ bool operator()(sal_uInt16 s1, sal_uInt16 s2) const
+ {
+ return s1 < s2;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////
+
+/** container class to create bit structures */
+class BitStream
+{
+public:
+ BitStream();
+
+ void writeUB( sal_uInt32 nValue, sal_uInt16 nBits );
+ void writeSB( sal_Int32 nValue, sal_uInt16 nBits );
+ void writeFB( sal_uInt32 nValue, sal_uInt16 nBits );
+
+ void pad();
+ void writeTo( SvStream& out );
+
+ sal_uInt32 getOffset() const;
+private:
+
+ std::vector< sal_uInt8 > maData;
+ sal_uInt8 mnBitPos;
+ sal_uInt8 mnCurrentByte;
+};
+
+///////////////////////////////////////////////////////////////////////
+
+/** this class collects all used glyphs for a given fonts and maps
+ characters to glyph ids.
+*/
+class FlashFont
+{
+public:
+ FlashFont( const Font& rFont, sal_uInt16 nId );
+ ~FlashFont();
+
+ sal_uInt16 getGlyph( sal_uInt16 nChar, VirtualDevice* pVDev );
+
+ void write( SvStream& out );
+
+ sal_uInt16 getID() const { return mnId; }
+ const Font& getFont() { return maFont; }
+
+private:
+ sal_uInt16 mnId;
+ const Font maFont;
+ std::map<sal_uInt16, sal_uInt16, ltuint16> maGlyphIndex;
+ sal_uInt16 mnNextIndex;
+ BitStream maGlyphData;
+ std::vector< sal_uInt16 > maGlyphOffsets;
+};
+
+typedef std::vector<FlashFont*> FontMap;
+
+///////////////////////////////////////////////////////////////////////
+
+/** this class helps creating flash tags */
+class Tag : public SvMemoryStream
+{
+public:
+ Tag( sal_uInt8 nTagId );
+
+ sal_uInt8 getTagId() const { return mnTagId; }
+
+ void write( SvStream& out );
+
+ void addUI32( sal_uInt32 nValue );
+ void addI32( sal_Int32 nValue );
+ void addUI16( sal_uInt16 nValue );
+ void addI16( sal_Int16 nValue );
+ void addUI8( sal_uInt8 nValue );
+ void addBits( BitStream& rIn );
+
+ void addRGBA( const Color& rColor );
+ void addRGB( const Color& rColor );
+ void addRect( const Rectangle& rRect );
+ void addMatrix( const Matrix3D& rMatrix );
+ void addString( const char* pString );
+ void addStream( SvStream& rIn );
+
+ static void writeMatrix( SvStream& rOut, const Matrix3D& rMatrix );
+ static void writeRect( SvStream& rOut, const Rectangle& rRect );
+
+private:
+ sal_uInt8 mnTagId;
+};
+
+///////////////////////////////////////////////////////////////////////
+
+/** this class helps to define flash sprites */
+class Sprite
+{
+public:
+ Sprite( sal_uInt16 nId );
+ ~Sprite();
+
+ void write( SvStream& out );
+
+ sal_uInt16 getId() const { return mnId; }
+
+ void addTag( Tag* pNewTag );
+
+private:
+ std::vector< Tag* > maTags;
+ sal_uInt16 mnId;
+ sal_uInt32 mnFrames;
+};
+
+///////////////////////////////////////////////////////////////////////
+
+/** this class stores a flash fill style for shapes */
+class FillStyle
+{
+public:
+ enum FillStyleType { solid = 0x00, linear_gradient = 0x10, radial_gradient = 0x12, tiled_bitmap = 0x40, clipped_bitmap = 0x41 };
+
+ /** this c'tor creates a solid fill style */
+ FillStyle( const Color& rSolidColor );
+
+ /** this c'tor creates a linear or radial gradient fill style */
+ FillStyle( const Rectangle& rBoundRect, const Gradient& rGradient );
+
+ /** this c'tor creates a tiled or clipped bitmap fill style */
+ FillStyle( sal_uInt16 nBitmapId, bool bClipped, const Matrix3D& rMatrix );
+
+ void addTo( Tag* pTag ) const;
+
+private:
+ void Impl_addGradient( Tag* pTag ) const;
+
+ FillStyleType meType;
+ Matrix3D maMatrix;
+ sal_uInt16 mnBitmapId;
+ Color maColor;
+ Gradient maGradient;
+ Rectangle maBoundRect;
+};
+
+///////////////////////////////////////////////////////////////////////
+
+/** this class creates a flash movie from vcl geometry */
+class Writer
+{
+ friend class FlashFont;
+
+public:
+ /** creates a writer for a new flash movie.
+ nDocWidth and nDocHeight are the dimensions of the movie.
+ They must be in 100th/mm.
+
+ An invisible shape with the size of the document is placed at depth 1
+ and it clips all shapes on depth 2 and 3.
+ */
+ Writer( sal_Int32 nDocWidthInput, sal_Int32 nDocHeightInput, sal_Int32 nDocWidth, sal_Int32 nDocHeight, sal_Int32 nJPEGcompressMode = -1 );
+ ~Writer();
+
+ void storeTo( com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > &xOutStream );
+
+ // geometry
+ void setClipping( const PolyPolygon* pClipPolyPolygon );
+
+ /** defines a flash shape from a filled polygon.
+ The coordinates must be in twips */
+ sal_uInt16 defineShape( const Polygon& rPoly, const FillStyle& rFillStyle );
+
+ /** defines a flash shape from a outlined polygon.
+ The coordinates must be in twips */
+ sal_uInt16 defineShape( const Polygon& rPoly, sal_uInt16 nLineWidth, const Color& rLineColor );
+
+ /** defines a flash shape from a filled polypolygon.
+ The coordinates must be in twips */
+ sal_uInt16 defineShape( const PolyPolygon& rPolyPoly, const FillStyle& rFillStyle );
+
+ /** defines a flash shape from a outlined polypolygon.
+ The coordinates must be in twips */
+ sal_uInt16 defineShape( const PolyPolygon& rPolyPoly, sal_uInt16 nLineWidth, const Color& rLineColor );
+
+ /** defines a flash shape from a vcl metafile.
+ The mapmode of the metafile is used to map all coordinates to twips.
+ A character id of a flash sprite is returned that contains all geometry
+ from the metafile.
+ */
+ sal_uInt16 defineShape( const GDIMetaFile& rMtf, sal_Int16 x = 0, sal_Int16 y = 0 );
+
+ /** defines a bitmap and returns its flash id.
+ */
+ sal_uInt16 defineBitmap( const BitmapEx& bmpSource, sal_Int32 nJPEGQualityLevel );
+
+ // control tags
+
+ /** inserts a place shape tag into the movie stream or the current sprite */
+ void placeShape( sal_uInt16 nID, sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y, sal_uInt16 nClipDepth = 0, const char* pName = NULL );
+
+ /** inserts a move shape tag into the movie stream or the current sprite */
+ void moveShape( sal_uInt16 nDepth, sal_Int32 x, sal_Int32 y );
+
+ /** inserts a remove shape tag into the movie stream or the current sprite */
+ void removeShape( sal_uInt16 nDepth );
+
+ /** inserts a show frame tag into the movie stream or the current sprite */
+ void showFrame();
+
+ /** sets the background color in the movie stream */
+ void setBackgroundColor( Color& rColor );
+
+ /** creates a new sprite and sets it as the current sprite for editing.
+ Only one sprite can be edited at one time */
+ sal_uInt16 startSprite();
+
+ /** ends editing of the curent sprites and adds it to the movie stream */
+ void endSprite();
+
+ /** inserts a doaction tag with an ActionStop */
+ void stop();
+
+ /** inserts a doaction tag with an ActionPlay */
+ void play();
+
+ /** inserts a doaction tag with an ActionStop, place a button on depth nDepth that
+ continues playback on click */
+ void waitOnClick( sal_uInt16 nDepth );
+
+ /** inserts a doaction tag with an ActionGotoFrame */
+ void gotoFrame( sal_uInt16 nFrame );
+
+ /** returns the character of a white rectangle with the dimensions of the document */
+ sal_uInt16 getWhiteBackgroundShapeId();
+
+#ifdef AUGUSTUS
+ /** stream out a sound. Should make it more intelligent so it interleaves with other items.*/
+ sal_Bool streamSound( const char * filename );
+#endif
+
+private:
+ Point map( const Point& rPoint ) const;
+ Size map( const Size& rSize ) const;
+ void map( PolyPolygon& rPolyPolygon ) const;
+ sal_Int32 mapRelative( sal_Int32 n100thMM ) const;
+
+ void startTag( sal_uInt8 nTagId );
+ void endTag();
+ sal_uInt16 createID();
+
+ void Impl_writeBmp( sal_uInt16 nBitmapId, sal_uInt32 width, sal_uInt32 height, sal_uInt8 *pCompressed, sal_uInt32 compressed_size );
+ void Impl_writeImage( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const Rectangle& rClipRect, bool bMap );
+ void Impl_writeJPEG(sal_uInt16 nBitmapId, const sal_uInt8* pJpgData, sal_uInt32 nJpgDataLength, sal_uInt8 *pCompressed, sal_uInt32 compressed_size, sal_Bool bStandardCompression );
+ void Impl_writeActions( const GDIMetaFile& rMtf );
+ void Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled );
+ void Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor );
+ void Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, sal_uInt8 nTransparence = 0);
+ void Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor );
+ void Impl_writeText( const Point& rPos, const String& rText, const long* pDXArray, long nWidth );
+ void Impl_writeGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient );
+ void Impl_writeLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = NULL );
+ void Impl_writeRect( const Rectangle& rRect, long nRadX, long nRadY );
+ void Impl_writeEllipse( const Point& rCenter, long nRadX, long nRadY );
+ bool Impl_writeFilling( SvtGraphicFill& rFilling );
+ bool Impl_writeStroke( SvtGraphicStroke& rStroke );
+
+ FlashFont& Impl_getFont( const Font& rFont );
+
+ static void Impl_addPolygon( BitStream& rBits, const Polygon& rPoly, sal_Bool bFilled );
+
+ static void Impl_addShapeRecordChange( BitStream& rBits, sal_Int16 dx, sal_Int16 dy, sal_Bool bFilled );
+ static void Impl_addStraightEdgeRecord( BitStream& rBits, sal_Int16 dx, sal_Int16 dy );
+ static void Impl_addCurvedEdgeRecord( BitStream& rBits, sal_Int16 control_dx, sal_Int16 control_dy, sal_Int16 anchor_dx, sal_Int16 anchor_dy );
+ static void Impl_addEndShapeRecord( BitStream& rBits );
+
+ static void Impl_addStraightLine( BitStream& rBits,
+ Point& rLastPoint,
+ const double P2x, const double P2y );
+ static void Impl_addQuadBezier( BitStream& rBits,
+ Point& rLastPoint,
+ const double P2x, const double P2y,
+ const double P3x, const double P3y );
+ static void Impl_quadBezierApprox( BitStream& rBits,
+ Point& rLastPoint,
+ const double d2,
+ const double P1x, const double P1y,
+ const double P2x, const double P2y,
+ const double P3x, const double P3y,
+ const double P4x, const double P4y );
+
+private:
+ FontMap maFonts;
+
+ sal_Int32 mnDocWidth;
+ sal_Int32 mnDocHeight;
+
+ // AS: Scaling factor for output.
+ double mnDocXScale;
+ double mnDocYScale;
+
+ sal_uInt16 mnWhiteBackgroundShapeId;
+ sal_uInt16 mnPageButtonId;
+
+ VirtualDevice* mpVDev;
+
+ const PolyPolygon* mpClipPolyPolygon;
+
+ /** holds the informations of the objects defined in the movie stream
+ while executing defineShape
+ */
+ typedef std::vector<sal_uInt16> CharacterIdVector;
+ CharacterIdVector maShapeIds;
+
+ Tag* mpTag;
+ Sprite* mpSprite;
+ std::stack<Sprite*> mvSpriteStack;
+ ChecksumCache mBitmapCache;
+
+ sal_uInt16 mnNextId;
+ sal_uInt32 mnFrames;
+
+// com::sun::star::uno::Reference< com::sun::star::io::XOutputStream > mxOutStream;
+ oslFileHandle mxOutStream;
+
+ utl::TempFile maMovieTempFile;
+ utl::TempFile maFontsTempFile;
+
+ SvStream* mpMovieStream;
+ SvStream* mpFontsStream;
+
+#ifdef AUGUSTUS
+ lame_global_flags *m_lame_flags;
+#endif
+
+ sal_uInt8 mnGlobalTransparency;
+ sal_Int32 mnJPEGCompressMode;
+ sal_Bool mbWrittenJPEGTables;
+};
+
+///////////////////////////////////////////////////////////////////////
+
+
+};
+
+#endif
diff --git a/filter/source/flash/swfwriter1.cxx b/filter/source/flash/swfwriter1.cxx
new file mode 100644
index 000000000000..6320e243ea6e
--- /dev/null
+++ b/filter/source/flash/swfwriter1.cxx
@@ -0,0 +1,1870 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfwriter1.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:04 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ * Thorsten Behrens (thorsten.behrens@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SWF_WRITER_HXX_
+#include "swfwriter.hxx"
+#endif
+
+#ifndef _SV_METAACT_HXX
+#include <vcl/metaact.hxx>
+#endif
+#ifndef _SV_GDIMTF_HXX
+#include <vcl/gdimtf.hxx>
+#endif
+#ifndef _SV_BMPACC_HXX
+#include <vcl/bmpacc.hxx>
+#endif
+#ifndef _SV_VIRDEV_HXX
+#include <vcl/virdev.hxx>
+#endif
+#ifndef _SV_METRIC_HXX
+#include <vcl/metric.hxx>
+#endif
+
+
+#ifndef _FILTER_HXX
+#include <svtools/Filter.hxx>
+#endif
+#ifndef _SVTOOLS_GRAPHICTOOLS_HXX_
+#include <svtools/graphictools.hxx>
+#endif
+
+#include <external/zlib/zlib.h>
+
+#ifndef _SV_SALBTYPE_HXX
+#include <vcl/salbtype.hxx>
+#endif
+
+using namespace ::swf;
+using namespace ::std;
+using namespace ::rtl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::beans;
+
+extern sal_uInt16 getMaxBitsUnsigned( sal_uInt32 nValue );
+extern sal_uInt16 getMaxBitsSigned( sal_Int32 nValue );
+
+static MapMode aTWIPSMode( MAP_TWIP );
+static MapMode a100thmmMode( MAP_100TH_MM );
+
+// -----------------------------------------------------------------------------
+
+Point Writer::map( const Point& rPoint ) const
+{
+ const MapMode& aSourceMapMode = mpVDev->GetMapMode();
+
+ Point retPoint = mpVDev->LogicToLogic( rPoint, &aSourceMapMode, &aTWIPSMode );
+
+ // AS: Produces a 'possible loss of data' warning that we can't fix without
+ // hurting code readability.
+ retPoint.X() *= mnDocXScale;
+ retPoint.Y() *= mnDocYScale;
+
+ return retPoint;
+}
+
+// -----------------------------------------------------------------------------
+
+Size Writer::map( const Size& rSize ) const
+{
+ const MapMode& aSourceMapMode = mpVDev->GetMapMode();
+
+ Size retSize = mpVDev->LogicToLogic( rSize, &aSourceMapMode, &aTWIPSMode );
+
+ // AS: Produces a 'possible loss of data' warning that we can't fix without
+ // hurting code readability.
+ retSize.Width() *= mnDocXScale;
+ retSize.Height() *= mnDocYScale;
+
+ return retSize;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::map( PolyPolygon& rPolyPolygon ) const
+{
+ const sal_uInt16 nPolyCount = rPolyPolygon.Count();
+ if( nPolyCount )
+ {
+ sal_uInt16 nPoly, nPoint, nPointCount;
+ for( nPoly = 0; nPoly < nPolyCount; nPoly++ )
+ {
+ Polygon& rPoly = rPolyPolygon[nPoly];
+ nPointCount = rPoly.GetSize();
+
+ for( nPoint = 0; nPoint < nPointCount; nPoint++ )
+ {
+ rPoly[nPoint] = map( rPoly[nPoint] );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Int32 Writer::mapRelative( sal_Int32 n100thMM ) const
+{
+ MapMode aSourceMapMode( mpVDev->GetMapMode() );
+ aSourceMapMode.SetOrigin( Point() );
+
+ sal_Int32 nTwips = mpVDev->LogicToLogic( Point( n100thMM, n100thMM ), &aSourceMapMode, &aTWIPSMode ).X();
+ return nTwips;
+}
+
+// -----------------------------------------------------------------------------
+
+/**
+*/
+void Writer::Impl_addPolygon( BitStream& rBits, const Polygon& rPoly, sal_Bool bFilled )
+{
+ Point aLastPoint( rPoly[0] );
+
+ Impl_addShapeRecordChange( rBits, _Int16(aLastPoint.X()),_Int16(aLastPoint.Y()), bFilled );
+
+ USHORT i = 0, nSize = rPoly.GetSize();
+
+ double d = 16.0f;
+
+ // points
+ while( ( i + 1 ) < nSize )
+ {
+ if( ( i + 3 ) < nSize )
+ {
+ BYTE P1( rPoly.GetFlags( i ) );
+ BYTE P4( rPoly.GetFlags( i + 3 ) );
+
+ if( ( POLY_NORMAL == P1 || POLY_SMOOTH == P1 || POLY_SYMMTR == P1 ) &&
+ ( POLY_CONTROL == rPoly.GetFlags( i + 1 ) ) &&
+ ( POLY_CONTROL == rPoly.GetFlags( i + 2 ) ) &&
+ ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) )
+ {
+ Impl_quadBezierApprox( rBits, aLastPoint, d*d,
+ rPoly.GetPoint( i ).X(), rPoly.GetPoint( i ).Y(),
+ rPoly.GetPoint( i+1 ).X(), rPoly.GetPoint( i+1 ).Y(),
+ rPoly.GetPoint( i+2 ).X(), rPoly.GetPoint( i+2 ).Y(),
+ rPoly.GetPoint( i+3 ).X(), rPoly.GetPoint( i+3 ).Y() );
+ i += 3;
+ continue;
+ }
+ }
+
+ ++i;
+
+ const Point aPolyPoint( rPoly[ i ] );
+ if( aPolyPoint != aLastPoint )
+ {
+ Impl_addStraightEdgeRecord( rBits, _Int16(aPolyPoint.X() - aLastPoint.X()),_Int16(aPolyPoint.Y() - aLastPoint.Y()));
+ aLastPoint = aPolyPoint;
+ }
+ }
+
+ if( bFilled && (rPoly[0] != rPoly[nSize-1]))
+ {
+ const Point aPolyPoint( rPoly[ 0 ] );
+ if( aPolyPoint != aLastPoint )
+ {
+ Impl_addStraightEdgeRecord( rBits, _Int16(aPolyPoint.X() - aLastPoint.X()),_Int16(aPolyPoint.Y() - aLastPoint.Y()));
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+/** exports a style change record with a move to (x,y) and depending on bFilled a line style 1 or fill style 1
+*/
+void Writer::Impl_addShapeRecordChange( BitStream& rBits, sal_Int16 dx, sal_Int16 dy, sal_Bool bFilled )
+{
+ rBits.writeUB( 0, 1 ); // TypeFlag
+ rBits.writeUB( 0, 1 ); // StateNewStyles
+ rBits.writeUB( !bFilled, 1 ); // StateLineStyle
+ rBits.writeUB( 0, 1 ); // StateFillStyle0
+ rBits.writeUB( bFilled, 1 ); // StateFillStyle1
+ rBits.writeUB( 1, 1 ); // StateMoveTo
+
+ sal_uInt16 nMoveBits = max( getMaxBitsSigned( dx ), getMaxBitsSigned( dy ) );
+
+ rBits.writeUB( nMoveBits, 5 ); // Number of bits per value
+ // TODO: Optimize horizontal and vertical lines
+ rBits.writeSB( dx, nMoveBits ); // DeltaX
+ rBits.writeSB( dy, nMoveBits ); // DeltaY
+
+ rBits.writeUB( 1, 1 ); // set FillStyle1 or LineStyle to 1
+}
+
+// -----------------------------------------------------------------------------
+
+/** exports a straight edge record
+*/
+void Writer::Impl_addStraightEdgeRecord( BitStream& rBits, sal_Int16 dx, sal_Int16 dy )
+{
+ rBits.writeUB( 1, 1 ); // TypeFlag
+ rBits.writeUB( 1, 1 ); // StraightFlag
+
+ sal_uInt16 nBits = max( getMaxBitsSigned( dx ), getMaxBitsSigned( dy ) );
+
+ rBits.writeUB( nBits - 2, 4 ); // Number of bits per value
+
+ if( (dx != 0) && (dy != 0) )
+ {
+ rBits.writeUB( 1, 1 ); // GeneralLineFlag
+ rBits.writeSB( dx, nBits ); // DeltaX
+ rBits.writeSB( dy, nBits ); // DeltaY
+ }
+ else
+ {
+ rBits.writeUB( 0, 1 );
+ rBits.writeUB( ( dx == 0 ), 1 );
+ if( dx == 0 )
+ {
+ rBits.writeSB( dy, nBits ); // DeltaY
+ }
+ else
+ {
+ rBits.writeSB( dx, nBits ); // DeltaX
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+/** exports a curved edge record
+*/
+void Writer::Impl_addCurvedEdgeRecord( BitStream& rBits, sal_Int16 control_dx, sal_Int16 control_dy, sal_Int16 anchor_dx, sal_Int16 anchor_dy )
+{
+ rBits.writeUB( 1, 1 ); // TypeFlag
+ rBits.writeUB( 0, 1 ); // CurvedFlag
+
+ sal_uInt8 nBits = static_cast<sal_uInt8>(
+ max( getMaxBitsSigned( control_dx ),
+ max( getMaxBitsSigned( control_dy ),
+ max( getMaxBitsSigned( anchor_dx ),
+ max( getMaxBitsSigned( anchor_dy ), (sal_uInt16)3 ) ) ) ) );
+
+ rBits.writeUB( nBits - 2, 4 ); // Number of bits per value
+
+ rBits.writeSB( control_dx, nBits ); // DeltaX
+ rBits.writeSB( control_dy, nBits ); // DeltaY
+ rBits.writeSB( anchor_dx, nBits ); // DeltaX
+ rBits.writeSB( anchor_dy, nBits ); // DeltaY
+}
+
+// -----------------------------------------------------------------------------
+
+/** exports a end shape record
+*/
+void Writer::Impl_addEndShapeRecord( BitStream& rBits )
+{
+ rBits.writeUB( 0, 6 );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled )
+{
+ PolyPolygon aPolyPoly( rPoly );
+ Impl_writePolyPolygon( aPolyPoly, bFilled );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writePolygon( const Polygon& rPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor )
+{
+ PolyPolygon aPolyPoly( rPoly );
+ Impl_writePolyPolygon( aPolyPoly, bFilled, rFillColor, rLineColor );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, sal_uInt8 nTransparence /* = 0 */ )
+{
+ Color aLineColor( mpVDev->GetLineColor() );
+ if( 0 == aLineColor.GetTransparency() )
+ aLineColor.SetTransparency( nTransparence );
+ Color aFillColor( mpVDev->GetFillColor() );
+ if( 0 == aFillColor.GetTransparency() )
+ aFillColor.SetTransparency( nTransparence );
+ Impl_writePolyPolygon(rPolyPoly, bFilled, aFillColor, aLineColor );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bFilled, const Color& rFillColor, const Color& rLineColor )
+{
+ PolyPolygon aPolyPoly( rPolyPoly );
+
+ if( aPolyPoly.Count() )
+ {
+ map( aPolyPoly );
+
+ if( mpClipPolyPolygon )
+ rPolyPoly.GetIntersection( *mpClipPolyPolygon, aPolyPoly );
+
+ sal_uInt16 nID;
+ if( bFilled )
+ {
+ Color aFillColor( rFillColor );
+ if( 0 != mnGlobalTransparency )
+ aFillColor.SetTransparency( mnGlobalTransparency );
+
+ FillStyle aStyle( aFillColor );
+ nID = defineShape( aPolyPoly, aStyle );
+ }
+ else
+ {
+ Color aLineColor( rLineColor );
+ if( 0 != mnGlobalTransparency )
+ aLineColor.SetTransparency( mnGlobalTransparency );
+
+ nID = defineShape( aPolyPoly, 1, aLineColor );
+ }
+ maShapeIds.push_back( nID );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+/** a gradient is a transition from one color to another, rendered inside a given polypolygon */
+void Writer::Impl_writeGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient )
+{
+ if( rPolyPoly.Count() )
+ {
+ PolyPolygon aPolyPolygon( rPolyPoly );
+ map( aPolyPolygon );
+
+ if( (rGradient.GetStyle() == GRADIENT_LINEAR) || (rGradient.GetStyle() == GRADIENT_RADIAL) )
+ {
+ const Rectangle aBoundRect( aPolyPolygon.GetBoundRect() );
+
+ FillStyle aFillStyle( aBoundRect, rGradient );
+
+ sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
+ maShapeIds.push_back( nShapeId );
+ }
+ else
+ {
+ setClipping( &aPolyPolygon );
+
+ // render the gradient filling to simple polygons
+ {
+ GDIMetaFile aTmpMtf;
+ mpVDev->AddGradientActions( aPolyPolygon.GetBoundRect(), rGradient, aTmpMtf );
+ Impl_writeActions( aTmpMtf );
+ }
+
+ setClipping( NULL );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::setClipping( const PolyPolygon* pClipPolyPolygon )
+{
+ mpClipPolyPolygon = pClipPolyPolygon;
+}
+
+// -----------------------------------------------------------------------------
+
+// AS: Just comparing fonts straight up is too literal. There are some
+// differences in font that actually require different glyphs to be defined,
+// and some that don't. This function is meant to capture all the differences
+// that we care about.
+bool compare_fonts_for_me(const Font& rFont1, const Font& rFont2)
+{
+ return rFont1.GetName() == rFont2.GetName() &&
+ rFont1.GetWeight() == rFont2.GetWeight() &&
+ rFont1.GetItalic() == rFont2.GetItalic() &&
+ rFont1.IsOutline() == rFont2.IsOutline() &&
+ rFont1.IsShadow() == rFont2.IsShadow() &&
+ rFont1.GetRelief() == rFont2.GetRelief();
+}
+
+// -----------------------------------------------------------------------------
+
+FlashFont& Writer::Impl_getFont( const Font& rFont )
+{
+ FontMap::iterator aIter( maFonts.begin() );
+ const FontMap::iterator aEnd( maFonts.end() );
+
+ while( aIter != aEnd )
+ {
+ const Font tempFont = (*aIter)->getFont();
+ if( compare_fonts_for_me(tempFont, rFont) )
+ {
+ return **aIter;
+ }
+
+ aIter++;
+ }
+
+ FlashFont* pFont = new FlashFont( rFont, createID() );
+ maFonts.push_back( pFont );
+ return *pFont;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeText( const Point& rPos, const String& rText, const long* pDXArray, long nWidth )
+{
+ sal_uInt32 nLen = rText.Len();
+
+ if( nLen )
+ {
+ Size aNormSize;
+ long* pOwnArray;
+ long* pDX;
+
+ // get text sizes
+ if( pDXArray )
+ {
+ pOwnArray = NULL;
+ aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
+ pDX = (long*) pDXArray;
+ }
+ else
+ {
+ pOwnArray = new long[ nLen ];
+ aNormSize = Size( mpVDev->GetTextArray( rText, pOwnArray ), 0 );
+ pDX = pOwnArray;
+ }
+
+ if( nLen > 1 )
+ {
+ aNormSize.Width() = pDX[ nLen - 2 ] + mpVDev->GetTextWidth( rText.GetChar( (USHORT) nLen - 1 ) );
+
+ if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
+ {
+ const double fFactor = (double) nWidth / aNormSize.Width();
+
+ sal_uInt32 i;
+ for( i = 0; i < ( nLen - 1 ); i++ )
+ pDX[ i ] = FRound( pDX[ i ] * fFactor );
+ }
+ }
+
+ Font aOldFont( mpVDev->GetFont() );
+ Point aBaseLinePos( rPos );
+
+ Font aFont(aOldFont);
+ short nOrientation = aFont.GetOrientation();
+ aFont.SetOrientation( 0 );
+ aFont.SetUnderline(UNDERLINE_NONE);
+ aFont.SetStrikeout(STRIKEOUT_NONE);
+ mpVDev->SetFont( aFont );
+
+ const FontMetric aMetric( mpVDev->GetFontMetric() );
+
+ FlashFont& rFlashFont = Impl_getFont( aFont );
+
+ // always adjust text position to match baseline alignment
+ switch( aOldFont.GetAlign() )
+ {
+ case( ALIGN_TOP ):
+ aBaseLinePos.Y() += aMetric.GetAscent();
+ break;
+
+ case( ALIGN_BOTTOM ):
+ aBaseLinePos.Y() -= aMetric.GetDescent();
+ break;
+
+ default:
+ break;
+ }
+
+ // get mapped text position
+ const Point aPt( map( aBaseLinePos ) );
+
+ // write text element
+
+/* test code to create a bound rect, not realy working for rotated text
+ Size aTextSize( map( Size( mpVDev->GetTextWidth( rText ), mpVDev->GetTextHeight() ) ) );
+ Point aMetricPoint( map( Point( aMetric.GetLeading(), aMetric.GetAscent() ) ) );
+
+ Point aTmpPoint( map( Point( - aMetric.GetLeading(), - aMetric.GetAscent() ) ) ); ;
+ Rectangle aTmpRectangle(aTmpPoint, aTextSize );
+ Polygon aPoly( aTmpRectangle );
+
+ aPoly.Rotate( aTmpPoint, (USHORT) nOrientation );
+
+ Rectangle aTextBoundRect( aPoly.GetBoundRect() );
+
+ aPoly.Move( aPt.X(), aPt.Y() - map( Size( 0, aMetric.GetDescent() ) ).Height() );
+
+*/
+
+#if 0 // makes the calculated bound rect visible for debuging
+{
+ Polygon aTmpPoly( aPoly );
+ sal_uInt16 nID = FlashGeometryExporter::writePolygonShape( aMovieStream, aTmpPoly, false, Color(COL_MAGENTA), Color(COL_MAGENTA), mpClipPolyPolygon );
+ ImplPlaceObject( nID );
+}
+#endif
+
+ // CL: This is still a hack until we figure out how to calculate a correct bound rect
+ // for rotatet text
+ Rectangle textBounds( 0, 0, static_cast<long>(mnDocWidth*mnDocXScale), static_cast<long>(mnDocHeight*mnDocYScale) );
+
+ Matrix3D m;
+ m.Rotate( static_cast<double>(nOrientation) * F_PI1800 );
+ m.Translate( double(aPt.X()), double(aPt.Y()) );
+
+ sal_Int16 nHeight = _Int16( map( Size( 0, aFont.GetHeight() ) ).Height() );
+
+ startTag( TAG_DEFINETEXT );
+
+ sal_uInt16 nTextId = createID();
+
+ mpTag->addUI16( nTextId );
+ mpTag->addRect( textBounds );
+ mpTag->addMatrix( m );
+
+ sal_uInt8 nGlyphBits = 16;
+ sal_uInt8 nAdvanceBits = 16;
+
+ mpTag->addUI8( nGlyphBits );
+ mpTag->addUI8( nAdvanceBits );
+
+ // text style change record
+ mpTag->addUI8( 0x8c );
+ mpTag->addUI16( rFlashFont.getID() );
+ mpTag->addRGB( mpVDev->GetTextColor() );
+ mpTag->addUI16( _uInt16( nHeight ) );
+
+ DBG_ASSERT( nLen <= 127, "TODO: handle text with more than 127 characters" );
+
+ // Glyph record
+ mpTag->addUI8( (sal_uInt8) nLen );
+
+ BitStream aBits;
+
+ sal_Int32 nLastDX = 0;
+ sal_Int32 nAdvance;
+ sal_uInt32 i;
+ for( i = 0; i < nLen; i++ )
+ {
+ if( i < (nLen-1) )
+ {
+ nAdvance = pDX[i] - nLastDX;
+ nLastDX = pDX[i];
+ }
+ else
+ {
+ nAdvance = 0;
+ }
+
+ aBits.writeUB( rFlashFont.getGlyph(rText.GetChar(_uInt16(i)),mpVDev), nGlyphBits );
+ aBits.writeSB( _Int16(map( Size( nAdvance, 0 ) ).Width() ), nAdvanceBits );
+ }
+
+ mpTag->addBits( aBits );
+ mpTag->addUI8( 0 );
+
+ endTag();
+
+ maShapeIds.push_back( nTextId );
+
+ // AS: Write strikeout and underline, if neccessary. This code was originally taken from the SVG
+ // export facility, although the positioning had to be tweaked a little. I can't explain the
+ // numbers, but the flash lines up very well with the original OOo document. All of this should
+ // probably be converted to polygons as part of the meta file, though, as we don't handle any
+ // fancy lines (like dashes).
+ if( aOldFont.GetStrikeout() || aOldFont.GetUnderline() )
+ {
+ Polygon aPoly( 4 );
+ const long nLineHeight = Max( (long) FRound( aMetric.GetLineHeight() * 0.05 ), (long) 1 );
+
+ if( aOldFont.GetStrikeout() )
+ {
+ aPoly[ 0 ].X() = aBaseLinePos.X();
+ aPoly[ 0 ].Y() = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 ) - nLineHeight;
+ aPoly[ 1 ].X() = aPoly[ 0 ].X() + aNormSize.Width() - 1;
+ aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
+ aPoly[ 2 ].X() = aPoly[ 1 ].X();
+ aPoly[ 2 ].Y() = aPoly[ 1 ].Y() + nLineHeight - 1;
+ aPoly[ 3 ].X() = aPoly[ 0 ].X();
+ aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
+
+ Impl_writePolygon( aPoly, sal_True, aOldFont.GetColor(), aOldFont.GetColor() );
+ }
+
+ // AS: The factor of 1.5 on the nLineHeight is a magic number. I'm not sure why it works,
+ // but it looks good to me.
+ if( aOldFont.GetUnderline() )
+ {
+ aPoly[ 0 ].X() = aBaseLinePos.X();
+ aPoly[ 0 ].Y() = static_cast<long>(aBaseLinePos.Y() + 1.5*nLineHeight);
+ aPoly[ 1 ].X() = aPoly[ 0 ].X() + aNormSize.Width() - 1;
+ aPoly[ 1 ].Y() = aPoly[ 0 ].Y();
+ aPoly[ 2 ].X() = aPoly[ 1 ].X();
+ aPoly[ 2 ].Y() = aPoly[ 1 ].Y() + nLineHeight - 1;
+ aPoly[ 3 ].X() = aPoly[ 0 ].X();
+ aPoly[ 3 ].Y() = aPoly[ 2 ].Y();
+
+ Impl_writePolygon( aPoly, sal_True, aOldFont.GetColor(), aOldFont.GetColor() );
+ }
+ }
+
+ mpVDev->SetFont( aOldFont );
+ delete[] pOwnArray;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// AS: Because JPEGs require the alpha channel provided seperately (JPEG does not
+// natively support alpha channel, but SWF lets you provide it seperately), we
+// extract the alpha channel into a seperate array here.
+void getBitmapData( const BitmapEx& aBmpEx, sal_uInt8*& tgadata, sal_uInt8*& tgaAlphadata, sal_uInt32& nWidth, sal_uInt32& nHeight )
+{
+ if( !aBmpEx.IsEmpty() )
+ {
+ Bitmap aBmp( aBmpEx.GetBitmap() );
+ BitmapReadAccess* pRAcc = aBmp.AcquireReadAccess();
+
+ if( pRAcc )
+ {
+ AlphaMask aAlpha;
+ nWidth = pRAcc->Width();
+ nHeight = pRAcc->Height();
+ tgadata = new sal_uInt8[nWidth*nHeight*4];
+ tgaAlphadata = new sal_uInt8[nWidth*nHeight];
+ sal_uInt8* p = tgadata, *pAlpha = tgaAlphadata;
+
+
+ if( aBmpEx.IsAlpha() )
+ aAlpha = aBmpEx.GetAlpha();
+ else if( aBmpEx.IsTransparent() )
+ aAlpha = aBmpEx.GetMask();
+ else
+ {
+ sal_uInt8 cAlphaVal = 0;
+ aAlpha = AlphaMask( aBmp.GetSizePixel(), &cAlphaVal );
+ }
+
+ BitmapReadAccess* pAAcc = aAlpha.AcquireReadAccess();
+
+ if( pAAcc )
+ {
+ for( sal_uInt32 nY = 0; nY < nHeight; nY++ )
+ {
+ for( sal_uInt32 nX = 0; nX < nWidth; nX++ )
+ {
+ const sal_uInt8 nAlpha = pAAcc->GetPixel( nY, nX ).GetIndex();
+ const BitmapColor aPixelColor( pRAcc->GetColor( nY, nX ) );
+
+ if( nAlpha == 0xff )
+ {
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+ }
+ else
+ {
+ *p++ = 0xff-nAlpha;
+ *p++ = aPixelColor.GetRed();
+ *p++ = aPixelColor.GetGreen();
+ *p++ = aPixelColor.GetBlue();
+ }
+ *pAlpha++ = 0xff - nAlpha;
+ }
+ }
+
+ aAlpha.ReleaseAccess( pAAcc );
+ }
+
+ aBmp.ReleaseAccess( pRAcc );
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+sal_uInt16 Writer::defineBitmap( const BitmapEx &bmpSource, sal_Int32 nJPEGQualityLevel )
+{
+ ULONG bmpChecksum = bmpSource.GetChecksum();
+
+ ChecksumCache::iterator it = mBitmapCache.find(bmpChecksum);
+
+ // AS: We already exported this bitmap, so just return its ID.
+ if (mBitmapCache.end() != it)
+ return it->second;
+
+ sal_uInt16 nBitmapId = createID();
+ mBitmapCache[bmpChecksum] = nBitmapId;
+
+ // AS: OK, we have a good image, so now we decide whether or not to JPEG it or
+ // or Lossless compress it.
+
+ //Figure out lossless size
+ sal_uInt8 *pImageData, *pAlphaData;
+ sal_uInt32 width, height;
+
+ getBitmapData( bmpSource, pImageData, pAlphaData, width, height );
+ sal_uInt32 raw_size = width * height * 4;
+ sal_uInt32 compressed_size = raw_size + (sal_uInt32)(raw_size/100) + 12;
+ sal_uInt8 *pCompressed = new sal_uInt8[ compressed_size ];
+
+ if(compress2(pCompressed, &compressed_size, pImageData, raw_size, Z_BEST_COMPRESSION) != Z_OK)
+ DBG_ASSERT( false, "compress2 failed!" );
+
+ // AS: SWF files let you provide an Alpha mask for JPEG images, but we have
+ // to ZLIB compress the alpha channel seperately.
+ sal_uInt32 alpha_compressed_size = 0;
+ sal_uInt8 *pAlphaCompressed = NULL;
+ if (bmpSource.IsAlpha() || bmpSource.IsTransparent())
+ {
+ alpha_compressed_size = width * height + (sal_uInt32)(raw_size/100) + 12;
+ pAlphaCompressed = new sal_uInt8[ compressed_size ];
+
+ if(compress2(pAlphaCompressed, &alpha_compressed_size, pAlphaData, width * height, Z_BEST_COMPRESSION) != Z_OK)
+ DBG_ASSERT( false, "compress2 failed!" );
+ }
+
+ //Figure out JPEG size
+ const sal_uInt8* pJpgData;
+ sal_uInt32 nJpgDataLength = -1;
+
+ Graphic aGraphic( bmpSource );
+ SvMemoryStream aDstStm( 65535, 65535 );
+
+ GraphicFilter aFilter;
+ Sequence< PropertyValue > aFilterData(nJPEGQualityLevel != -1);
+ if( nJPEGQualityLevel != -1 )
+ {
+ aFilterData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM("Quality"));
+ aFilterData[0].Value <<= nJPEGQualityLevel;
+ }
+
+ if( aFilter.ExportGraphic( aGraphic, String(), aDstStm,
+ aFilter.GetExportFormatNumberForShortName( OUString( RTL_CONSTASCII_USTRINGPARAM( JPG_SHORTNAME ) ) ),
+ false, &aFilterData ) == ERRCODE_NONE )
+ {
+ pJpgData = reinterpret_cast<const sal_uInt8*>(aDstStm.GetData());
+ nJpgDataLength = aDstStm.Seek( STREAM_SEEK_TO_END );
+ }
+
+ // AS: Ok, now go ahead and use whichever is smaller. If JPEG is smaller, then
+ // we have to export as TAG_DEFINEBITSJPEG3 in the case that there is alpha
+ // channel data.
+ if (nJpgDataLength + alpha_compressed_size < compressed_size)
+ Impl_writeJPEG(nBitmapId, pJpgData, nJpgDataLength, pAlphaCompressed, alpha_compressed_size, nJPEGQualityLevel == mnJPEGCompressMode);
+ else
+ Impl_writeBmp( nBitmapId, width, height, pCompressed, compressed_size );
+
+ delete[] pCompressed;
+ delete[] pAlphaCompressed;
+ delete[] pImageData;
+ delete[] pAlphaData;
+
+ return nBitmapId;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeImage( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const Rectangle& rClipRect, bool bNeedToMapClipRect )
+{
+ if( !!rBmpEx )
+ {
+ BitmapEx bmpSource( rBmpEx );
+
+ Rectangle originalPixelRect(Point(), bmpSource.GetSizePixel());
+
+ Point srcPt( map(rPt) );
+ Size srcSize( map(rSz) );
+ Rectangle destRect( srcPt, srcSize );
+
+ // AS: Christian, my scaling factors are different than yours, and work better for me.
+ // However, I can't explain why exactly. I got some of this by trial and error.
+ double XScale = static_cast<double>(originalPixelRect.GetWidth())/destRect.GetWidth();
+ double YScale = static_cast<double>(originalPixelRect.GetHeight())/destRect.GetHeight();
+
+ // AS: If rClipRect has a value set, then we need to crop the bmp appropriately.
+ // If a map event already occurred in the metafile, then we do not need to map
+ // the clip rect as it's already been done.
+ if (!rClipRect.IsEmpty())
+ {
+ // AS: Christian, I also don't understand why bNeedToMapClipRect is necessary, but it
+ // works like a charm. Sometimes the map event is missing from the metafile, but why?
+ Size clipSize( bNeedToMapClipRect ? map(rClipRect.GetSize()) : rClipRect.GetSize() );
+ Rectangle clipRect(Point(), clipSize);
+ destRect.Intersection( clipRect );
+
+ Rectangle cropRect(destRect);
+
+ // AS: The bmp origion is always 0,0 so we have to adjust before we crop.
+ cropRect.Move(-srcPt.X(), -srcPt.Y());
+ // AS: Rectangle has no scale function (?!) so I do it manually...
+ Rectangle cropPixelRect(static_cast<long>(cropRect.Left()*XScale),
+ static_cast<long>(cropRect.Top()*YScale),
+ static_cast<long>(cropRect.Right()*XScale),
+ static_cast<long>(cropRect.Bottom()*YScale));
+
+ bmpSource.Crop(cropPixelRect);
+ }
+
+ if( !!bmpSource )
+ {
+ sal_Int32 nJPEGQuality = mnJPEGCompressMode;
+
+ Size szDestPixel = mpVDev->LogicToPixel(srcSize, aTWIPSMode);
+
+ double pixXScale = static_cast<double>(szDestPixel.Width()) / originalPixelRect.GetWidth();
+ double pixYScale = static_cast<double>(szDestPixel.Height()) / originalPixelRect.GetHeight();
+
+ // AS: If the image has been scaled down, then scale down the quality
+ // that we use for JPEG compression.
+ if (pixXScale < 1.0 && pixYScale < 1.0)
+ {
+
+ double qualityScale = (pixXScale + pixYScale)/2;
+
+ nJPEGQuality *= qualityScale;
+
+ if (nJPEGQuality < 10)
+ nJPEGQuality += 3;
+ }
+
+ sal_uInt16 nBitmapId = defineBitmap(bmpSource, nJPEGQuality);
+
+ Polygon aPoly( destRect );
+
+ // AS: Since images are being cropped now, no translation is normally necessary.
+ // However, some things like graphical bullet points are still get translated.
+ Matrix3D m;
+ m.Scale(1.0/XScale, 1.0/YScale);
+ if (destRect.Left() || destRect.Top())
+ m.Translate(destRect.Left(), destRect.Top());
+
+ FillStyle aFillStyle( nBitmapId, true, m );
+
+ sal_uInt16 nShapeId = defineShape( aPoly, aFillStyle );
+
+ maShapeIds.push_back( nShapeId );
+ }
+ }
+}
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeBmp( sal_uInt16 nBitmapId, sal_uInt32 width, sal_uInt32 height, sal_uInt8 *pCompressed, sal_uInt32 compressed_size )
+{
+ startTag( TAG_DEFINEBITSLOSSLESS2 );
+
+ mpTag->addUI16( nBitmapId );
+ mpTag->addUI8( 5 );
+ mpTag->addUI16( _uInt16(width) );
+ mpTag->addUI16( _uInt16(height) );
+
+ mpTag->Write( pCompressed, compressed_size );
+
+ endTag();
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeJPEG(sal_uInt16 nBitmapId, const sal_uInt8* pJpgData, sal_uInt32 nJpgDataLength, sal_uInt8 *pAlphaCompressed, sal_uInt32 alpha_compressed_size, sal_Bool bStandardCompression )
+{
+ // AS: Go through the actuall JPEG bits, seperating out the
+ // header fields from the actual image fields. Fields are
+ // identifed by 0xFFXX where XX is the field type. Both
+ // the header and the image need start and stop (D8 and D9),
+ // so that's why you see those written to both. I don't
+ // really know what the rest of these are, I got it to work
+ // kind of by trial and error and by comparing with known
+ // good SWF files.
+ sal_uInt8 cType = 0x01;
+ const sal_uInt8* pJpgSearch = pJpgData;
+ const sal_uInt8* pLastMark = pJpgData;
+
+ SvMemoryStream EncodingTableStream;
+ SvMemoryStream ImageBitsStream;
+ for (;pJpgSearch < pJpgData + nJpgDataLength; pJpgSearch++)
+ {
+ if (0xFF == *pJpgSearch)
+ {
+ sal_uInt32 nLength = pJpgSearch - pLastMark;
+
+ if (nLength > 0)
+ {
+ switch(cType)
+ {
+ case 0xD8:
+ EncodingTableStream.Write( pLastMark, nLength );
+ ImageBitsStream.Write( pLastMark, nLength );
+ break;
+
+ case 0x01:
+ case 0x02:
+ case 0xDB:
+ case 0xC4:
+ EncodingTableStream.Write( pLastMark, nLength );
+ break;
+
+ case 0xC1:
+ case 0xE0:
+ case 0xC0:
+ case 0xDA:
+ case 0x03:
+ case 0x00:
+ ImageBitsStream.Write( pLastMark, nLength );
+ break;
+
+ default:
+ DBG_ERROR( "JPEG marker I didn't handle!" );
+
+ }
+ }
+
+ cType = *(pJpgSearch + 1);
+ pLastMark = pJpgSearch;
+
+ // AS: The way that I'm checking for markers, we'll miss the
+ // one at the end, so I special case it :(
+ if (0xD9 == cType)
+ {
+ EncodingTableStream.Write( pLastMark, 2 );
+ ImageBitsStream.Write( pLastMark, 2 );
+ }
+ }
+ }
+
+ EncodingTableStream.Seek( STREAM_SEEK_TO_END );
+ sal_uInt32 nEncodingTableSize = EncodingTableStream.Tell();
+ EncodingTableStream.Seek( STREAM_SEEK_TO_BEGIN );
+
+ ImageBitsStream.Seek( STREAM_SEEK_TO_END );
+ sal_uInt32 nImageBitsSize = ImageBitsStream.Tell();
+ ImageBitsStream.Seek( STREAM_SEEK_TO_BEGIN );
+
+ // AS: If we need alpha support, use TAG_DEFINEBITSJPEG3.
+ if (alpha_compressed_size > 0)
+ {
+ startTag( TAG_DEFINEBITSJPEG3 );
+
+ mpTag->addUI16( nBitmapId );
+
+ mpTag->addUI32( nEncodingTableSize + nImageBitsSize );
+
+ mpTag->Write(EncodingTableStream.GetData(), nEncodingTableSize);
+ mpTag->Write(ImageBitsStream.GetData(), nImageBitsSize);
+
+ mpTag->Write( pAlphaCompressed, alpha_compressed_size );
+
+ endTag();
+ }
+ else if (!bStandardCompression)
+ {
+ startTag( TAG_DEFINEBITSJPEG2 );
+
+ mpTag->addUI16( nBitmapId );
+
+ mpTag->Write(EncodingTableStream.GetData(), nEncodingTableSize);
+ mpTag->Write(ImageBitsStream.GetData(), nImageBitsSize);
+
+ endTag();
+ }
+ else
+ {
+ if (!mbWrittenJPEGTables)
+ {
+ mbWrittenJPEGTables = true;
+ startTag( TAG_JPEGTABLES );
+
+ mpTag->Write(EncodingTableStream.GetData(), nEncodingTableSize);
+
+ endTag();
+ }
+
+ startTag( TAG_DEFINEBITS );
+
+ mpTag->addUI16( nBitmapId );
+ mpTag->Write(ImageBitsStream.GetData(), nImageBitsSize);
+
+ endTag();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor )
+{
+ Color aOldColor( mpVDev->GetLineColor() );
+ if( pLineColor )
+ mpVDev->SetLineColor( *pLineColor );
+
+ const Point aPtAry[2] = { rPt1, rPt2 };
+ Polygon aPoly( 2, aPtAry );
+ Impl_writePolyPolygon( aPoly, false );
+
+ mpVDev->SetLineColor( aOldColor );
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeRect( const Rectangle& rRect, long nRadX, long nRadY )
+{
+ if( (rRect.nTop == rRect.nBottom) || (rRect.nLeft == rRect.nRight) )
+ {
+ Color aColor( mpVDev->GetFillColor() );
+ Impl_writeLine( rRect.TopLeft(), rRect.BottomRight(), &aColor );
+ }
+ else
+ {
+ Polygon aPoly( rRect, nRadX, nRadY );
+ Impl_writePolyPolygon( aPoly, true );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeEllipse( const Point& rCenter, long nRadX, long nRadY )
+{
+ Polygon aPoly( rCenter, nRadX, nRadY );
+ Impl_writePolyPolygon( aPoly, false );
+}
+
+
+/** writes the stroke defined by SvtGraphicStroke and returns true or it returns
+ false if it can't handle this stroke.
+*/
+bool Writer::Impl_writeStroke( SvtGraphicStroke& rStroke )
+{
+ Polygon aPolygon;
+ rStroke.getPath( aPolygon );
+ PolyPolygon aPolyPolygon( aPolygon );
+
+ Rectangle aOldRect( aPolyPolygon.GetBoundRect() );
+
+ map( aPolyPolygon );
+
+ Rectangle aNewRect( aPolyPolygon.GetBoundRect() );
+
+ PolyPolygon aStartArrow;
+ rStroke.getStartArrow( aStartArrow );
+ if( 0 != aStartArrow.Count() )
+ return false; // todo: Implement line ends
+
+ PolyPolygon aEndArrow;
+ rStroke.getEndArrow( aEndArrow );
+ if( 0 != aEndArrow.Count() )
+ return false; // todo: Implement line ends
+
+ SvtGraphicStroke::DashArray aDashArray;
+ rStroke.getDashArray( aDashArray );
+ if( 0 != aDashArray.size() )
+ return false; // todo: implement dashes
+
+ double fTransparency = rStroke.getTransparency();
+ double fStrokeWidth = rStroke.getStrokeWidth();
+
+ Color aColor( mpVDev->GetLineColor() );
+
+ if( 0.0 != rStroke.getTransparency() )
+ aColor.SetTransparency( MinMax( rStroke.getTransparency() * 0xff, 0, 0xff ) );
+
+ sal_uInt16 nShapeId = defineShape( aPolyPolygon, mapRelative( rStroke.getStrokeWidth() ), aColor );
+ maShapeIds.push_back( nShapeId );
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+/** writes the filling defined by SvtGraphicFill and returns true or it returns
+ false if it can't handle this filling.
+*/
+bool Writer::Impl_writeFilling( SvtGraphicFill& rFilling )
+{
+ PolyPolygon aPolyPolygon;
+ rFilling.getPath( aPolyPolygon );
+
+ Rectangle aOldRect( aPolyPolygon.GetBoundRect() );
+
+ map( aPolyPolygon );
+
+ Rectangle aNewRect( aPolyPolygon.GetBoundRect() );
+
+ switch( rFilling.getFillType() )
+ {
+ case SvtGraphicFill::FillType::fillSolid:
+ {
+ Color aColor( rFilling.getFillColor() );
+
+ if( 0.0 != rFilling.getTransparency() )
+ aColor.SetTransparency( MinMax( rFilling.getTransparency() * 0xff, 0, 0xff ) );
+
+ FillStyle aFillStyle( aColor );
+
+ sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
+ maShapeIds.push_back( nShapeId );
+ }
+ break;
+ case SvtGraphicFill::FillType::fillGradient:
+ return false;
+ case SvtGraphicFill::FillType::fillHatch:
+ return false;
+ case SvtGraphicFill::FillType::fillTexture:
+ {
+ Graphic aGraphic;
+ rFilling.getGraphic( aGraphic );
+
+ // CL->AS: Should we also scale down the quality here depending on image scale?
+ sal_uInt16 nBitmapId = defineBitmap( aGraphic.GetBitmapEx(), mnJPEGCompressMode );
+
+ Matrix3D aMatrix;
+
+ SvtGraphicFill::Transform aTransform;
+
+ rFilling.getTransform( aTransform );
+
+ int a,b;
+ for( a = 0; a < 2; a++ )
+ {
+ for( b = 0; b < 3; b++ )
+ {
+ aMatrix[a][b] = aTransform.matrix[a*3+b];
+ }
+ }
+ aMatrix[2][0] = 0.0; aMatrix[2][1] = 0.0; aMatrix[2][2] = 1.0;
+
+ // scale bitmap
+ Rectangle originalPixelRect(Point(), aGraphic.GetBitmapEx().GetSizePixel());
+
+ double XScale = (double)aNewRect.GetWidth()/aOldRect.GetWidth();
+ double YScale = (double)aNewRect.GetHeight()/aOldRect.GetHeight();
+
+ aMatrix.Scale( XScale, YScale );
+
+ FillStyle aFillStyle( nBitmapId, !rFilling.IsTiling(), aMatrix );
+
+ sal_uInt16 nShapeId = defineShape( aPolyPolygon, aFillStyle );
+ maShapeIds.push_back( nShapeId );
+ }
+ break;
+ }
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_writeActions( const GDIMetaFile& rMtf )
+{
+ Rectangle clipRect;
+ bool bMap = false;
+ for( ULONG i = 0, nCount = rMtf.GetActionCount(); i < nCount; i++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( i );
+ const USHORT nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
+
+ Impl_writeLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor() );
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ const MetaPointAction* pA = (const MetaPointAction*) pAction;
+
+ Impl_writeLine( pA->GetPoint(), pA->GetPoint() );
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ const MetaLineAction* pA = (const MetaLineAction*) pAction;
+
+ Impl_writeLine( pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ Impl_writeRect( ( (const MetaRectAction*) pAction )->GetRect(), 0, 0 );
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
+
+ Impl_writeRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
+ const Rectangle& rRect = pA->GetRect();
+
+ Impl_writeEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1 );
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ case( META_PIE_ACTION ):
+ case( META_CHORD_ACTION ):
+ case( META_POLYGON_ACTION ):
+ {
+ Polygon aPoly;
+
+ switch( nType )
+ {
+ case( META_ARC_ACTION ):
+ {
+ const MetaArcAction* pA = (const MetaArcAction*) pAction;
+ aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_ARC );
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ const MetaPieAction* pA = (const MetaPieAction*) pAction;
+ aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_PIE );
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ const MetaChordAction* pA = (const MetaChordAction*) pAction;
+ aPoly = Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), POLY_CHORD );
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ aPoly = ( (const MetaPolygonAction*) pAction )->GetPolygon();
+ break;
+ }
+
+ if( aPoly.GetSize() )
+ {
+ Impl_writePolygon( aPoly, sal_True );
+ }
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ Impl_writePolygon( rPoly, sal_False );
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pAction;
+ const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+
+ if( rPolyPoly.Count() )
+ Impl_writePolyPolygon( rPolyPoly, sal_True );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
+
+ Polygon aPoly( pA->GetRect() );
+ Impl_writeGradientEx( aPoly, pA->GetGradient() );
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
+ Impl_writeGradientEx( pA->GetPolyPolygon(), pA->GetGradient() );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
+ GDIMetaFile aTmpMtf;
+
+ mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
+ Impl_writeActions( aTmpMtf );
+ }
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ {
+ const MetaTransparentAction* pA = (const MetaTransparentAction*) pAction;
+ const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+
+ if( rPolyPoly.Count() )
+ {
+ // convert transparence from percent into 0x00 - 0xff
+ sal_uInt8 nTransparence = (sal_uInt8) MinMax( FRound( pA->GetTransparence() * 2.55 ), 0, 255 );
+ Impl_writePolyPolygon( rPolyPoly, sal_True, nTransparence );
+ }
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pAction;
+ GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
+ Point aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
+ const Size aSrcSize( aTmpMtf.GetPrefSize() );
+ const Point aDestPt( pA->GetPoint() );
+ const Size aDestSize( pA->GetSize() );
+ const double fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
+ const double fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
+ long nMoveX, nMoveY;
+
+ if( fScaleX != 1.0 || fScaleY != 1.0 )
+ {
+ aTmpMtf.Scale( fScaleX, fScaleY );
+ aSrcPt.X() = FRound( aSrcPt.X() * fScaleX );
+ aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
+ }
+
+ nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
+
+ if( nMoveX || nMoveY )
+ aTmpMtf.Move( nMoveX, nMoveY );
+
+ const Gradient& rGradient = pA->GetGradient();
+ sal_uInt32 nLuminance = ((sal_Int32)rGradient.GetStartColor().GetLuminance() + (sal_Int32)rGradient.GetEndColor().GetLuminance() ) >> 1;
+
+ sal_uInt8 nOldGlobalTransparency = mnGlobalTransparency;
+ mnGlobalTransparency = (sal_uInt8)MinMax( nLuminance, 0, 0xff );
+
+ mpVDev->Push();
+ Impl_writeActions( aTmpMtf );
+ mpVDev->Pop();
+
+ mnGlobalTransparency = nOldGlobalTransparency;
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
+ const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
+ sal_Bool bFound = sal_False;
+
+ for( ULONG i = 0, nCount = aGDIMetaFile.GetActionCount(); ( i < nCount ) && !bFound; i++ )
+ {
+ const MetaAction* pSubstAct = aGDIMetaFile.GetAction( i );
+
+ if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
+ {
+ bFound = sal_True;
+ const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*) pSubstAct;
+ Impl_writeImage( pBmpScaleAction->GetBitmap(),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), clipRect, !bMap );
+ }
+ }
+ }
+ break;
+
+ case( META_COMMENT_ACTION ):
+ {
+ const MetaCommentAction* pA = (const MetaCommentAction*) pAction;
+ const BYTE* pData = pA->GetData();
+ 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 = rMtf.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 )
+ Impl_writeGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient());
+ }
+ else if( pA->GetComment().CompareIgnoreCaseToAscii( "XPATHFILL_SEQ_BEGIN" ) == COMPARE_EQUAL &&
+ pData )
+ {
+
+ // this comment encapsulates all high level information for a filling that caused
+ // the meta actions between the "XPATHFILL_SEQ_BEGIN" and "XPATHFILL_SEQ_END" comment.
+
+ SvtGraphicFill aFilling;
+ SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
+
+ // read the fill info
+ aMemStm >> aFilling;
+
+ // if impl_writeFilling can handle this high level filling, it returns true and we
+ // skip all meta actions until "XPATHFILL_SEQ_END"
+ if( Impl_writeFilling( aFilling ) )
+ {
+ bool bDone = sal_False;
+
+ while( !bDone && ( ++i < nCount ) )
+ {
+ pAction = rMtf.GetAction( i );
+
+ if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
+ ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XPATHFILL_SEQ_END" ) == COMPARE_EQUAL ) )
+ {
+ bDone = sal_True;
+ }
+ }
+ }
+ }
+ else if( pA->GetComment().CompareIgnoreCaseToAscii( "XPATHSTROKE_SEQ_BEGIN" ) == COMPARE_EQUAL &&
+ pData )
+ {
+
+ // this comment encapsulates all high level information for a filling that caused
+ // the meta actions between the "XPATHFILL_SEQ_BEGIN" and "XPATHFILL_SEQ_END" comment.
+
+ SvtGraphicStroke aStroke;
+ SvMemoryStream aMemStm( (void*)pData, pA->GetDataSize(), STREAM_READ );
+
+ // read the fill info
+ aMemStm >> aStroke;
+
+ // if impl_writeStroke can handle this high level stroke, it returns true and we
+ // skip all meta actions until "XPATHSTROKE_SEQ_END"
+ if( Impl_writeStroke( aStroke ) )
+ {
+ bool bDone = sal_False;
+
+ while( !bDone && ( ++i < nCount ) )
+ {
+ pAction = rMtf.GetAction( i );
+
+ if( ( pAction->GetType() == META_COMMENT_ACTION ) &&
+ ( ( (const MetaCommentAction*) pAction )->GetComment().CompareIgnoreCaseToAscii( "XPATHSTROKE_SEQ_END" ) == COMPARE_EQUAL ) )
+ {
+ bDone = sal_True;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+
+ Impl_writeImage( pA->GetBitmap(),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pA->GetBitmap().GetSizePixel(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ const MetaBmpAction* pA = (const MetaBmpAction*) pAction;
+ Impl_writeImage( pA->GetBitmap(),
+ pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel()),
+ Point(), pA->GetBitmap().GetSizePixel(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
+ Impl_writeImage( pA->GetBitmap(),
+ pA->GetDestPoint(), pA->GetDestSize(),
+ pA->GetSrcPoint(), pA->GetSrcSize(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ const MetaBmpExAction* pA = (const MetaBmpExAction*) pAction;
+ Impl_writeImage( pA->GetBitmapEx(),
+ pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
+ Point(), pA->GetBitmapEx().GetSizePixel(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ Impl_writeImage( pA->GetBitmapEx(),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pA->GetBitmapEx().GetSizePixel(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
+ Impl_writeImage( pA->GetBitmapEx(),
+ pA->GetDestPoint(), pA->GetDestSize(),
+ pA->GetSrcPoint(), pA->GetSrcSize(), clipRect, !bMap );
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ const MetaTextAction* pA = (const MetaTextAction*) pAction;
+ Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, 0);
+ }
+ break;
+
+ case( META_TEXTRECT_ACTION ):
+ {
+ const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
+ Impl_writeText( pA->GetRect().TopLeft(), pA->GetText(), NULL, 0 );
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
+ Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), pA->GetDXArray(), 0 );
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ {
+ const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
+ Impl_writeText( pA->GetPoint(), String( pA->GetText(), pA->GetIndex(), pA->GetLen() ), NULL, pA->GetWidth() );
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pAction;
+ clipRect = pA->GetRect();
+ }
+ case( META_CLIPREGION_ACTION ):
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( mpVDev );
+// mbClipAttrChanged = sal_True;
+ }
+ break;
+
+ case( META_MAPMODE_ACTION ): bMap = true;
+ case( META_REFPOINT_ACTION ):
+ case( META_LINECOLOR_ACTION ):
+ case( META_FILLCOLOR_ACTION ):
+ case( META_TEXTLINECOLOR_ACTION ):
+ case( META_TEXTFILLCOLOR_ACTION ):
+ case( META_TEXTCOLOR_ACTION ):
+ case( META_TEXTALIGN_ACTION ):
+ case( META_FONT_ACTION ):
+ case( META_PUSH_ACTION ):
+ case( META_POP_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( mpVDev );
+ }
+ break;
+
+ case( META_RASTEROP_ACTION ):
+ case( META_MASK_ACTION ):
+ case( META_MASKSCALE_ACTION ):
+ case( META_MASKSCALEPART_ACTION ):
+ case( META_WALLPAPER_ACTION ):
+ case( META_TEXTLINE_ACTION ):
+ case( META_LAYOUTMODE_ACTION ):
+ {
+ // !!! >>> we don't want to support these actions
+ }
+ break;
+
+ default:
+ //DBG_ERROR( "FlashActionWriter::ImplWriteActions: unsupported MetaAction #" );
+ break;
+ }
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+
+
+void Writer::Impl_addStraightLine( BitStream& rBits, Point& rLastPoint,
+ const double P2x, const double P2y )
+{
+ Point aPoint( FRound(P2x), FRound(P2y) );
+
+ Impl_addStraightEdgeRecord( rBits, _Int16(aPoint.X() - rLastPoint.X()),_Int16(aPoint.Y() - rLastPoint.Y()));
+ rLastPoint = aPoint;
+
+}
+
+// -----------------------------------------------------------------------------
+
+void Writer::Impl_addQuadBezier( BitStream& rBits, Point& rLastPoint,
+ const double P2x, const double P2y,
+ const double P3x, const double P3y )
+{
+
+ Point aControlPoint( FRound(P2x), FRound(P2y) );
+ Point aAnchorPoint( FRound(P3x), FRound(P3y) );
+
+ Impl_addCurvedEdgeRecord( rBits,
+ _Int16(aControlPoint.X() - rLastPoint.X()),_Int16(aControlPoint.Y() - rLastPoint.Y()),
+ _Int16(aAnchorPoint.X() - aControlPoint.X()),_Int16(aAnchorPoint.Y() - aControlPoint.Y()) );
+ rLastPoint = aAnchorPoint;
+}
+
+// -----------------------------------------------------------------------------
+
+/* Approximate given cubic bezier curve by quadratic bezier segments */
+void Writer::Impl_quadBezierApprox( BitStream& rBits,
+ Point& rLastPoint,
+ const double d2,
+ const double P1x, const double P1y,
+ const double P2x, const double P2y,
+ const double P3x, const double P3y,
+ const double P4x, const double P4y )
+{
+ // Check for degenerate case, where the given cubic bezier curve
+ // is already quadratic: P4 == 3P3 - 3P2 + P1
+ if( P4x == 3.0*P3x - 3.0*P2x + P1x &&
+ P4y == 3.0*P3y - 3.0*P2y + P1y )
+ {
+ Impl_addQuadBezier( rBits, rLastPoint,
+ 3.0/2.0*P2x - 1.0/2.0*P1x, 3.0/2.0*P2y - 1.0/2.0*P1y,
+ P4x, P4y);
+ }
+ else
+ {
+ // Create quadratic segment for given cubic:
+ // Start and end point must coincide, determine quadratic control
+ // point in such a way that it lies on the intersection of the
+ // tangents at start and end point, resp. Thus, both cubic and
+ // quadratic curve segments will match in 0th and 1st derivative
+ // at the start and end points
+
+ // Intersection of P2P1 and P4P3
+ // (P2y-P4y)(P3x-P4x)-(P2x-P4x)(P3y-P4y)
+ // lambda = -------------------------------------
+ // (P1x-P2x)(P3y-P4y)-(P1y-P2y)(P3x-P4x)
+ //
+ // Intersection point IP is now
+ // IP = P2 + lambda(P1-P2)
+ //
+ const double nominator( (P2y-P4y)*(P3x-P4x) - (P2x-P4x)*(P3y-P4y) );
+ const double denominator( (P1x-P2x)*(P3y-P4y) - (P1y-P2y)*(P3x-P4x) );
+ const double lambda( nominator / denominator );
+
+ const double IPx( P2x + lambda*( P1x - P2x) );
+ const double IPy( P2y + lambda*( P1y - P2y) );
+
+ // Introduce some alias names: quadratic start point is P1, end
+ // point is P4, control point is IP
+ const double QP1x( P1x );
+ const double QP1y( P1y );
+ const double QP2x( IPx );
+ const double QP2y( IPy );
+ const double QP3x( P4x );
+ const double QP3y( P4y );
+
+ // Adapted bezier flatness test (lecture notes from R. Schaback,
+ // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
+ //
+ // ||C(t) - Q(t)|| <= max ||c_j - q_j||
+ // 0<=j<=n
+ //
+ // In this case, we don't need the distance from the cubic bezier
+ // to a straight line, but to a quadratic bezier. The c_j's are
+ // the cubic bezier's bernstein coefficients, the q_j's the
+ // quadratic bezier's. We have the c_j's given, the q_j's can be
+ // calculated from QPi like this (sorry, mixed index notation, we
+ // use [1,n], formulas use [0,n-1]):
+ //
+ // q_0 = QP1 = P1
+ // q_1 = 1/3 QP1 + 2/3 QP2
+ // q_2 = 2/3 QP2 + 1/3 QP3
+ // q_3 = QP3 = P4
+ //
+ // We can drop case 0 and 3, since there the curves coincide
+ // (distance is zero)
+
+ // calculate argument of max for j=1 and j=2
+ const double fJ1x( P2x - 1.0/3.0*QP1x - 2.0/3.0*QP2x );
+ const double fJ1y( P2y - 1.0/3.0*QP1y - 2.0/3.0*QP2y );
+ const double fJ2x( P3x - 2.0/3.0*QP2x - 1.0/3.0*QP3x );
+ const double fJ2y( P3y - 2.0/3.0*QP2y - 1.0/3.0*QP3y );
+
+ // stop if distance from cubic curve is guaranteed to be bounded by d
+ // Should denominator be 0: then P1P2 and P3P4 are parallel (P1P2^T R[90,P3P4] = 0.0),
+ // meaning that either we have a straight line or an inflexion point (see else block below)
+ if( 0.0 != denominator &&
+ ::std::max( fJ1x*fJ1x + fJ1y*fJ1y,
+ fJ2x*fJ2x + fJ2y*fJ2y) < d2 )
+ {
+ // requested resolution reached.
+ // Add end points to output file.
+ // order is preserved, since this is so to say depth first traversal.
+ Impl_addQuadBezier( rBits, rLastPoint,
+ QP2x, QP2y,
+ QP3x, QP3y);
+ }
+ else
+ {
+ // Maybe subdivide further
+
+ // This is for robustness reasons, since the line intersection
+ // method below gets instable if the curve gets closer to a
+ // straight line. If the given cubic bezier does not deviate by
+ // more than d/4 from a straight line, either:
+ // - take the line (that's what we do here)
+ // - express the line by a quadratic bezier
+
+ // Perform bezier flatness test (lecture notes from R. Schaback,
+ // Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
+ //
+ // ||P(t) - L(t)|| <= max ||b_j - b_0 - j/n(b_n - b_0)||
+ // 0<=j<=n
+ //
+ // What is calculated here is an upper bound to the distance from
+ // a line through b_0 and b_3 (P1 and P4 in our notation) and the
+ // curve. We can drop 0 and n from the running indices, since the
+ // argument of max becomes zero for those cases.
+ const double fJ1x( P2x - P1x - 1.0/3.0*(P4x - P1x) );
+ const double fJ1y( P2y - P1y - 1.0/3.0*(P4y - P1y) );
+ const double fJ2x( P3x - P1x - 2.0/3.0*(P4x - P1x) );
+ const double fJ2y( P3y - P1y - 2.0/3.0*(P4y - P1y) );
+
+ // stop if distance from line is guaranteed to be bounded by d/4
+ if( ::std::max( fJ1x*fJ1x + fJ1y*fJ1y,
+ fJ2x*fJ2x + fJ2y*fJ2y) < d2/16.0 )
+ {
+ // do not subdivide further, add straight line instead
+ Impl_addStraightLine( rBits, rLastPoint, P4x, P4y);
+ }
+ else
+ {
+ // deCasteljau bezier arc, split at t=0.5
+ // Foley/vanDam, p. 508
+ const double L1x( P1x ), L1y( P1y );
+ const double L2x( (P1x + P2x)*0.5 ), L2y( (P1y + P2y)*0.5 );
+ const double Hx ( (P2x + P3x)*0.5 ), Hy ( (P2y + P3y)*0.5 );
+ const double L3x( (L2x + Hx)*0.5 ), L3y( (L2y + Hy)*0.5 );
+ const double R4x( P4x ), R4y( P4y );
+ const double R3x( (P3x + P4x)*0.5 ), R3y( (P3y + P4y)*0.5 );
+ const double R2x( (Hx + R3x)*0.5 ), R2y( (Hy + R3y)*0.5 );
+ const double R1x( (L3x + R2x)*0.5 ), R1y( (L3y + R2y)*0.5 );
+ const double L4x( R1x ), L4y( R1y );
+
+ // subdivide further
+ Impl_quadBezierApprox(rBits, rLastPoint, d2, L1x, L1y, L2x, L2y, L3x, L3y, L4x, L4y);
+ Impl_quadBezierApprox(rBits, rLastPoint, d2, R1x, R1y, R2x, R2y, R3x, R3y, R4x, R4y);
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+// TODO: Why do I need this?
+
+extern "C"
+{
+
+int ZEXPORT compress2 ( Bytef * dest, uLongf * destLen, const Bytef * source, uLong sourceLen, int level)
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+}
diff --git a/filter/source/flash/swfwriter2.cxx b/filter/source/flash/swfwriter2.cxx
new file mode 100644
index 000000000000..e32bfff6561a
--- /dev/null
+++ b/filter/source/flash/swfwriter2.cxx
@@ -0,0 +1,727 @@
+/*************************************************************************
+ *
+ * $RCSfile: swfwriter2.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: cl $ $Date: 2002-11-21 14:58:04 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Christian Lippka (christian.lippka@sun.com)
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SWF_WRITER_HXX_
+#include "swfwriter.hxx"
+#endif
+
+#ifndef _SV_VIRDEV_HXX
+#include <vcl/virdev.hxx>
+#endif
+
+using namespace ::swf;
+using namespace ::std;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::io;
+using ::rtl::OUString;
+using ::rtl::OString;
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 getMaxBitsUnsigned( sal_uInt32 nValue )
+{
+ sal_uInt16 nBits = 0;
+
+ while( nValue )
+ {
+ nBits++;
+ nValue >>= 1;
+ }
+
+ return nBits;
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt16 getMaxBitsSigned( sal_Int32 nValue )
+{
+ if( nValue < 0 )
+ nValue *= -1;
+
+ return getMaxBitsUnsigned( static_cast< sal_uInt32 >(nValue) ) + 1;
+}
+
+// -----------------------------------------------------------------------------
+
+BitStream::BitStream()
+{
+ mnBitPos = 8;
+ mnCurrentByte = 0;
+}
+
+// -----------------------------------------------------------------------------
+
+void BitStream::writeUB( sal_uInt32 nValue, sal_uInt16 nBits )
+{
+ while( nBits != 0 )
+ {
+ mnCurrentByte |= nValue << (32 - nBits) >> (32 - mnBitPos);
+
+ if ( nBits > mnBitPos )
+ {
+ nBits -= mnBitPos;
+ mnBitPos = 0;
+ }
+ else
+ {
+ mnBitPos -= nBits;
+ nBits = 0;
+ }
+
+ if( 0 == mnBitPos )
+ pad();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void BitStream::writeSB( sal_Int32 nValue, sal_uInt16 nBits )
+{
+ writeUB( static_cast< sal_uInt32 >(nValue), nBits );
+}
+
+// -----------------------------------------------------------------------------
+
+void BitStream::writeFB( sal_uInt32 nValue, sal_uInt16 nBits )
+{
+ writeUB( nValue, nBits );
+}
+
+// -----------------------------------------------------------------------------
+
+void BitStream::pad()
+{
+ if( 8 != mnBitPos )
+ {
+ maData.push_back( mnCurrentByte );
+ mnCurrentByte = 0;
+ mnBitPos = 8;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void BitStream::writeTo( SvStream& out )
+{
+ pad();
+
+ vector< sal_uInt8 >::iterator aIter( maData.begin() );
+ const vector< sal_uInt8>::iterator aEnd( maData.end() );
+ while(aIter != aEnd)
+ {
+ out << (*aIter++);
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uInt32 BitStream::getOffset() const
+{
+ return maData.size();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+Tag::Tag( sal_uInt8 nTagId )
+{
+ mnTagId = nTagId;
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::write( SvStream &out )
+{
+ Seek( STREAM_SEEK_TO_END );
+ sal_uInt32 nSize = Tell();
+ Seek( STREAM_SEEK_TO_BEGIN );
+
+ if( mnTagId != 0xff )
+ {
+ bool bLarge = nSize > 62;
+
+ sal_uInt16 nCode = ( mnTagId << 6 ) | ( bLarge ? 0x3f : _uInt16(nSize) );
+
+ out << (sal_uInt8)nCode;
+ out << (sal_uInt8)(nCode >> 8);
+
+ if( bLarge )
+ {
+ sal_uInt32 nTmp = nSize;
+
+ out << (sal_uInt8)nTmp;
+ nTmp >>= 8;
+ out << (sal_uInt8)nTmp;
+ nTmp >>= 8;
+ out << (sal_uInt8)nTmp;
+ nTmp >>= 8;
+ out << (sal_uInt8)nTmp;
+ }
+ }
+
+ out.Write( GetData(), nSize );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addI32( sal_Int32 nValue )
+{
+ addUI32( static_cast<sal_uInt32>( nValue ) );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addUI32( sal_uInt32 nValue )
+{
+ *this << nValue;
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addI16( sal_Int16 nValue )
+{
+ addUI16( static_cast<sal_uInt16>( nValue ) );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addUI16( sal_uInt16 nValue )
+{
+ *this << (sal_uInt8)nValue;
+ *this << (sal_uInt8)(nValue >> 8);
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addUI8( sal_uInt8 nValue )
+{
+ *this << (sal_uInt8)nValue;
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addBits( BitStream& rIn )
+{
+ rIn.writeTo( *this );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addRGBA( const Color& rColor )
+{
+ addUI8( rColor.GetRed() );
+ addUI8( rColor.GetGreen() );
+ addUI8( rColor.GetBlue() );
+ addUI8( 0xff - rColor.GetTransparency() );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addRGB( const Color& rColor )
+{
+ addUI8( rColor.GetRed() );
+ addUI8( rColor.GetGreen() );
+ addUI8( rColor.GetBlue() );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addRect( const Rectangle& rRect )
+{
+ writeRect( *this, rRect );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::writeRect( SvStream& rOut, const Rectangle& rRect )
+{
+ BitStream aBits;
+
+ sal_Int16 minX, minY, maxX, maxY;
+
+ if( rRect.nLeft < rRect.nRight )
+ {
+ minX = _Int16(rRect.nLeft); maxX = _Int16(rRect.nRight);
+ }
+ else
+ {
+ maxX = _Int16(rRect.nLeft); minX = _Int16(rRect.nRight);
+ }
+
+
+ if( rRect.nTop < rRect.nBottom )
+ {
+ minY = _Int16(rRect.nTop); maxY = _Int16(rRect.nBottom);
+ }
+ else
+ {
+ maxY = _Int16(rRect.nTop); minY = _Int16(rRect.nBottom);
+ }
+
+ // AS: Figure out the maximum nubmer of bits required to represent any of the
+ // rectangle coordinates. Since minX or minY could be negative, they could
+ // actually require more bits than maxX or maxY.
+ // AS: Christian, can they be negative, or is that a wasted check?
+ // CL: I think so, f.e. for shapes that have the top and/or left edge outside
+ // the page origin
+ sal_uInt8 nBits1 = max( getMaxBitsSigned( minX ), getMaxBitsSigned( minY ) );
+ sal_uInt8 nBits2 = max( getMaxBitsSigned( maxX ), getMaxBitsSigned( maxY ) );
+ sal_uInt8 nBitsMax = max( nBits1, nBits2 );
+
+ aBits.writeUB( nBitsMax, 5 );
+ aBits.writeSB( minX, nBitsMax );
+ aBits.writeSB( maxX, nBitsMax );
+ aBits.writeSB( minY, nBitsMax );
+ aBits.writeSB( maxY, nBitsMax );
+
+ aBits.writeTo( rOut );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addMatrix( const Matrix3D& rMatrix )
+{
+ writeMatrix( *this, rMatrix );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::writeMatrix( SvStream& rOut, const Matrix3D& rMatrix )
+{
+
+ BitStream aBits;
+
+ const sal_uInt8 bHasScale = rMatrix[0][0] != 1 || rMatrix[1][1] != 1;
+
+ aBits.writeUB( bHasScale, 1 );
+
+ if( bHasScale )
+ {
+ sal_uInt8 nScaleBits = 31;
+
+ aBits.writeUB( nScaleBits, 5 );
+ aBits.writeFB( getFixed( rMatrix[0][0] ), nScaleBits ); // Scale X
+ aBits.writeFB( getFixed( rMatrix[1][1] ), nScaleBits ); // Scale Y
+ }
+
+ const sal_uInt8 bHasRotate = rMatrix[0][1] != 0 || rMatrix[1][0] != 0;
+
+ aBits.writeUB( bHasRotate, 1 );
+
+ if( bHasRotate )
+ {
+ sal_uInt8 nRotateBits = 31;
+
+ aBits.writeUB( nRotateBits, 5 );
+ aBits.writeFB( getFixed( rMatrix[0][1] ), nRotateBits ); // RotateSkew0
+ aBits.writeFB( getFixed( rMatrix[1][0] ), nRotateBits ); // RotateSkew1
+ }
+
+ sal_uInt8 nTranslateBits = 16;
+
+ aBits.writeUB( nTranslateBits, 5 );
+ aBits.writeSB( (sal_Int16)rMatrix[0][2], nTranslateBits ); // Translate X
+ aBits.writeSB( (sal_Int16)rMatrix[1][2], nTranslateBits ); // Translate Y
+
+ aBits.writeTo( rOut );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addString( const char* pString )
+{
+ if( pString )
+ {
+ while( *pString )
+ addUI8( *pString++ );
+ }
+
+ addUI8( 0 );
+}
+
+// -----------------------------------------------------------------------------
+
+void Tag::addStream( SvStream& rIn )
+{
+ *this << rIn;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+Sprite::Sprite( sal_uInt16 nId )
+: mnId( nId ), mnFrames(0)
+{
+}
+
+// -----------------------------------------------------------------------------
+
+Sprite::~Sprite()
+{
+ for(vector< Tag* >::iterator i = maTags.begin(); i != maTags.end(); i++)
+ delete *i;
+}
+
+// -----------------------------------------------------------------------------
+
+void Sprite::write( SvStream& out )
+{
+ SvMemoryStream aTmp;
+ for(vector< Tag* >::iterator i = maTags.begin(); i != maTags.end(); i++)
+ (*i)->write( aTmp );
+
+ aTmp.Seek(0);
+
+ Tag aTag( TAG_DEFINESPRITE );
+ aTag.addUI16( mnId );
+ aTag.addUI16( _uInt16( mnFrames ) );
+ aTag.addStream( aTmp );
+ aTag.write( out );
+}
+
+// -----------------------------------------------------------------------------
+
+void Sprite::addTag( Tag* pNewTag )
+{
+ if( pNewTag )
+ {
+ if( pNewTag->getTagId() == TAG_SHOWFRAME )
+ mnFrames++;
+
+ maTags.push_back( pNewTag );
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+sal_uInt32 swf::getFixed( double fValue )
+{
+ sal_Int16 nUpper = (sal_Int16)floor(fValue);
+ sal_uInt16 nLower = (sal_uInt16)((fValue - floor(fValue))*0x10000);
+
+ sal_uInt32 temp = ((sal_Int32)nUpper)<<16;
+ temp |= nLower;
+
+ return temp;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+/** constructs a new flash font for the given VCL Font */
+FlashFont::FlashFont( const Font& rFont, sal_uInt16 nId )
+: maFont( rFont ), mnNextIndex(0), mnId( nId )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+FlashFont::~FlashFont()
+{
+}
+
+// -----------------------------------------------------------------------------
+
+/** gets the glyph id for the given character. The glyphs are created on demand */
+sal_uInt16 FlashFont::getGlyph( sal_uInt16 nChar, VirtualDevice* pVDev )
+{
+ // see if we already created a glyph for this character
+ std::map<sal_uInt16, sal_uInt16, ltuint16>::iterator aIter( maGlyphIndex.find(nChar) );
+ if( aIter != maGlyphIndex.end() )
+ {
+ return aIter->second;
+ }
+
+ // if not, we create one now
+
+ maGlyphIndex[nChar] = mnNextIndex;
+
+ Font aOldFont( pVDev->GetFont() );
+ Font aNewFont( aOldFont );
+ aNewFont.SetAlign( ALIGN_BASELINE );
+ pVDev->SetFont( aNewFont );
+ aOldFont.SetOrientation(0);
+
+ // let the virtual device convert the character to polygons
+ PolyPolygon aPolyPoly;
+ pVDev->GetTextOutline( aPolyPoly, nChar );
+
+ maGlyphOffsets.push_back( _uInt16( maGlyphData.getOffset() ) );
+
+ // Number of fill and line index bits set to 1
+ maGlyphData.writeUB( 0x11, 8 );
+
+ const sal_uInt16 nCount = aPolyPoly.Count();
+ sal_uInt16 i,n;
+ for( i = 0; i < nCount; i++ )
+ {
+ Polygon& rPoly = aPolyPoly[ i ];
+
+ const USHORT nSize = rPoly.GetSize();
+ if( nSize )
+ {
+ // convert polygon to flash EM_SQUARE (1024x1024)
+ for( n = 0; n < nSize; n++ )
+ {
+ Point aPoint( rPoly[n] );
+ aPoint.X() = static_cast<long>((double(aPoint.X()) * 1024.0 ) / double(aOldFont.GetHeight()));
+ aPoint.Y() = static_cast<long>((double(aPoint.Y()) * 1024.0 ) / double(aOldFont.GetHeight()));
+ rPoly[n] = aPoint;
+ }
+ Writer::Impl_addPolygon( maGlyphData, rPoly, true );
+ }
+ }
+ Writer::Impl_addEndShapeRecord( maGlyphData );
+
+ maGlyphData.pad();
+
+ sal_uInt32 nOffset = maGlyphData.getOffset();
+
+ pVDev->SetFont( aOldFont );
+
+ return mnNextIndex++;
+}
+
+// -----------------------------------------------------------------------------
+
+void FlashFont::write( SvStream& out )
+{
+ Tag aTag( TAG_DEFINEFONT );
+
+ aTag.addUI16( mnId );
+
+ sal_uInt16 nGlyphs = _uInt16( maGlyphOffsets.size() );
+ sal_uInt16 nOffset = nGlyphs * sizeof( sal_uInt16 );
+
+ for(vector< sal_uInt16 >::iterator i = maGlyphOffsets.begin(); i != maGlyphOffsets.end(); i++)
+ aTag.addUI16( nOffset + (*i) );
+
+ aTag.addBits( maGlyphData );
+
+ aTag.write( out );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+/** this c'tor creates a solid fill style */
+FillStyle::FillStyle( const Color& rSolidColor )
+: meType( solid ),
+ maColor( rSolidColor )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+/** this c'tor creates a tiled or clipped bitmap fill style */
+FillStyle::FillStyle( sal_uInt16 nBitmapId, bool bClipped, const Matrix3D& rMatrix )
+: meType( bClipped ? clipped_bitmap : tiled_bitmap ),
+ maMatrix( rMatrix ),
+ mnBitmapId( nBitmapId )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+FillStyle::FillStyleType Impl_getFillStyleType( const Gradient& rGradient )
+{
+ switch( rGradient.GetStyle() )
+ {
+ case GradientStyle_ELLIPTICAL:
+ case GradientStyle_RADIAL:
+ return FillStyle::radial_gradient;
+// case GradientStyle_AXIAL:
+// case GradientStyle_SQUARE:
+// case GradientStyle_RECT:
+// case GradientStyle_LINEAR:
+ default:
+ return FillStyle::linear_gradient;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+/** this c'tor creates a linear or radial gradient fill style */
+FillStyle::FillStyle( const Rectangle& rBoundRect, const Gradient& rGradient )
+: meType( Impl_getFillStyleType( rGradient ) ),
+ maGradient( rGradient ),
+ maBoundRect( rBoundRect )
+{
+}
+
+// -----------------------------------------------------------------------------
+
+void FillStyle::addTo( Tag* pTag ) const
+{
+ pTag->addUI8( meType );
+ switch( meType )
+ {
+ case solid:
+ pTag->addRGBA( maColor );
+ break;
+ case linear_gradient:
+ case radial_gradient:
+ Impl_addGradient( pTag );
+ break;
+ case tiled_bitmap:
+ case clipped_bitmap:
+ pTag->addUI16( mnBitmapId );
+ pTag->addMatrix( maMatrix );
+ break;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+struct GradRecord
+{
+ sal_uInt8 mnRatio;
+ Color maColor;
+
+ GradRecord( sal_uInt8 nRatio, const Color& rColor ) : mnRatio( nRatio ), maColor( rColor ) {}
+};
+
+// TODO: better emulation of our gradients
+void FillStyle::Impl_addGradient( Tag* pTag ) const
+{
+ vector< struct GradRecord > aGradientRecords;
+
+ Matrix3D m;
+
+ m.Rotate( (maGradient.GetAngle() - 900) * F_PI1800 );
+
+ switch( maGradient.GetStyle() )
+ {
+ case GradientStyle_ELLIPTICAL:
+ case GradientStyle_RADIAL:
+ {
+ aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetEndColor() ) );
+ aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetStartColor() ) );
+
+ double tx = ( maGradient.GetOfsX() * 32768.0 ) / 100.0;
+ double ty = ( maGradient.GetOfsY() * 32768.0 ) / 100.0;
+ double scalex = (double)maBoundRect.GetWidth() / 32768.0;
+ double scaley = (double)maBoundRect.GetHeight() / 32768.0;
+
+ m.Scale( 1.2, 1.2 );
+
+ if( scalex > scaley )
+ {
+ double scale_move = scaley / scalex;
+
+ m.Translate( tx, scale_move * ty );
+
+
+ m.Scale( scalex, scalex );
+ }
+ else
+ {
+ double scale_move = scalex / scaley;
+
+ m.Translate( scale_move * tx, ty );
+
+
+ m.Scale( scaley, scaley );
+ }
+
+ }
+ break;
+ case GradientStyle_AXIAL:
+ {
+ aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetEndColor() ) );
+ aGradientRecords.push_back( GradRecord( 0x80, maGradient.GetStartColor() ) );
+ aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetEndColor() ) );
+ double tx = ( 32768.0 / 2.0 );
+ double ty = ( 32768.0 / 2.0 );
+ double scalex = (double)maBoundRect.GetWidth() / 32768.0;
+ double scaley = (double)maBoundRect.GetHeight() / 32768.0;
+
+ m.Translate( tx, ty );
+ m.Scale( scalex, scaley );
+ }
+ break;
+ case GradientStyle_SQUARE:
+ case GradientStyle_RECT:
+ case GradientStyle_LINEAR:
+ {
+ aGradientRecords.push_back( GradRecord( 0x00, maGradient.GetStartColor() ) );
+ aGradientRecords.push_back( GradRecord( 0xff, maGradient.GetEndColor() ) );
+ double scalex = (double)maBoundRect.GetWidth() / 32768.0;
+ double scaley = (double)maBoundRect.GetHeight() / 32768.0;
+
+ m.Scale( scalex, scaley );
+
+ m.Translate( maBoundRect.GetWidth() / 2.0, maBoundRect.GetHeight() / 2.0 );
+ }
+ break;
+ }
+
+ m.Translate( maBoundRect.nLeft, maBoundRect.nTop );
+
+ pTag->addMatrix( m );
+
+ DBG_ASSERT( aGradientRecords.size() < 8, "Illegal FlashGradient!" );
+
+ pTag->addUI8( static_cast<sal_uInt8>( aGradientRecords.size() ) );
+
+ for(std::vector< GradRecord >::iterator i = aGradientRecords.begin(); i != aGradientRecords.end(); i++)
+ {
+ pTag->addUI8( (*i).mnRatio );
+ pTag->addRGBA( (*i).maColor );
+ }
+}
+