summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@suse.cz>2013-01-01 22:48:32 +0100
committerPetr Mladek <pmladek@suse.cz>2013-01-08 16:12:44 +0100
commit3a571a93df6dc4be855ac5c6433f28e57531fae5 (patch)
tree40b132bcaad94af7951296ddd46772e8e867def3 /vcl
parenta03f34ce76108b452f2bb655e3a551dcd23ab644 (diff)
Move GraphicFilter class to vcl.
Change-Id: I2318eeda59cee1cfdb074f9a90fd7d8d80aab19f Signed-off-by: Cor Nouws <oolst@nouenoff.nl> Signed-off-by: Olivier Hallot <olivier.hallot@documentfoundation.org> Signed-off-by: Adolfo Jayme Barrientos <fitoschido@ubuntu.com> Signed-off-by: Michael Meeks <michael.meeks@suse.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/CppunitTest_vcl_filters_test.mk62
-rw-r--r--vcl/inc/vcl/FilterConfigItem.hxx86
-rw-r--r--vcl/inc/vcl/graphicfilter.hxx360
-rw-r--r--vcl/inc/vcl/wmf.hxx67
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/README7
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2004-0691-1.bmpbin0 -> 313 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2006-0006-1.bmpbin0 -> 43218 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2007-2244-1.bmpbin0 -> 21424 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2008-5870-1.bmp1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmpbin0 -> 18862 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emfbin0 -> 576 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emfbin0 -> 3524 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emfbin0 -> 1075 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emfbin0 -> 3380 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emfbin0 -> 3524 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emfbin0 -> 7068 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gifbin0 -> 328 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gifbin0 -> 47778 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gifbin0 -> 2382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gifbin0 -> 10998 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gifbin0 -> 2876 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-1.jpgbin0 -> 4098 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-4.jpgbin0 -> 4098 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpgbin0 -> 12000000 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpgbin0 -> 1674 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpgbin0 -> 2634 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpgbin0 -> 8903 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png3
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.pngbin0 -> 346 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.pngbin0 -> 2495 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.pngbin0 -> 18470 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/png/pass/black.pngbin0 -> 175 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/sgv/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/sgv/indeterminate/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/sgv/pass/.gitignore0
-rwxr-xr-xvcl/qa/cppunit/graphicfilter/data/sgv/pass/SaveAsPicture.sgvbin0 -> 1212 bytes
-rwxr-xr-xvcl/qa/cppunit/graphicfilter/data/sgv/pass/faxpfeil.sgvbin0 -> 1291 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676bin0 -> 684 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmfbin0 -> 218 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmfbin0 -> 12178 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmfbin0 -> 68 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore0
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmfbin0 -> 684 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf1
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmfbin0 -> 238 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1238-1.wmfbin0 -> 382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1245-1.wmfbin0 -> 382 bytes
-rw-r--r--vcl/qa/cppunit/graphicfilter/filters-test.cxx108
-rw-r--r--vcl/source/filter/FilterConfigCache.cxx561
-rw-r--r--vcl/source/filter/FilterConfigCache.hxx131
-rw-r--r--vcl/source/filter/FilterConfigItem.cxx439
-rw-r--r--vcl/source/filter/graphicfilter.cxx2449
-rw-r--r--vcl/source/filter/graphicfilter2.cxx1135
-rw-r--r--vcl/source/filter/igif/decode.cxx207
-rw-r--r--vcl/source/filter/igif/decode.hxx60
-rw-r--r--vcl/source/filter/igif/gifread.cxx865
-rw-r--r--vcl/source/filter/igif/gifread.hxx133
-rw-r--r--vcl/source/filter/ixbm/xbmread.cxx385
-rw-r--r--vcl/source/filter/ixbm/xbmread.hxx87
-rw-r--r--vcl/source/filter/ixpm/rgbtable.hxx689
-rw-r--r--vcl/source/filter/ixpm/xpmread.cxx690
-rw-r--r--vcl/source/filter/ixpm/xpmread.hxx123
-rw-r--r--vcl/source/filter/jpeg/jpeg.cxx777
-rw-r--r--vcl/source/filter/jpeg/jpeg.h64
-rw-r--r--vcl/source/filter/jpeg/jpeg.hxx123
-rw-r--r--vcl/source/filter/jpeg/jpegc.c278
-rw-r--r--vcl/source/filter/sgf.ini136
-rw-r--r--vcl/source/filter/sgfbram.cxx532
-rw-r--r--vcl/source/filter/sgfbram.hxx151
-rw-r--r--vcl/source/filter/sgffilt.hxx40
-rw-r--r--vcl/source/filter/sgvmain.cxx966
-rw-r--r--vcl/source/filter/sgvmain.hxx352
-rw-r--r--vcl/source/filter/sgvspln.cxx861
-rw-r--r--vcl/source/filter/sgvspln.hxx63
-rw-r--r--vcl/source/filter/sgvtext.cxx1277
-rw-r--r--vcl/source/filter/wmf/emfwr.cxx1412
-rw-r--r--vcl/source/filter/wmf/emfwr.hxx93
-rw-r--r--vcl/source/filter/wmf/enhwmf.cxx1418
-rw-r--r--vcl/source/filter/wmf/winmtf.cxx2239
-rw-r--r--vcl/source/filter/wmf/winmtf.hxx890
-rw-r--r--vcl/source/filter/wmf/winwmf.cxx1503
-rw-r--r--vcl/source/filter/wmf/wmf.cxx110
-rw-r--r--vcl/source/filter/wmf/wmfwr.cxx2052
-rw-r--r--vcl/source/filter/wmf/wmfwr.hxx220
105 files changed, 24212 insertions, 0 deletions
diff --git a/vcl/CppunitTest_vcl_filters_test.mk b/vcl/CppunitTest_vcl_filters_test.mk
new file mode 100644
index 000000000000..b6db6efc463f
--- /dev/null
+++ b/vcl/CppunitTest_vcl_filters_test.mk
@@ -0,0 +1,62 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+# Version: MPL 1.1 / GPLv3+ / LGPLv3+
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License or as specified alternatively below. You may obtain a copy of
+# the License at http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# Major Contributor(s):
+# Copyright (C) 2011 Red Hat, Inc., Caolán McNamara <caolanm@redhat.com>
+# (initial developer)
+#
+# All Rights Reserved.
+#
+# For minor contributions see the git repository.
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+# instead of those above.
+
+$(eval $(call gb_CppunitTest_CppunitTest,svtools_filters_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,svtools_filters_test, \
+ svtools/qa/cppunit/filters-test \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,svtools_filters_test, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ svt \
+ test \
+ tl \
+ unotest \
+ vcl \
+ $(gb_UWINAPI) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,svtools_filters_test,\
+ udkapi \
+ offapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,svtools_filters_test))
+
+$(eval $(call gb_CppunitTest_use_components,svtools_filters_test,\
+ configmgr/source/configmgr \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,svtools_filters_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/inc/vcl/FilterConfigItem.hxx b/vcl/inc/vcl/FilterConfigItem.hxx
new file mode 100644
index 000000000000..e20ebf8dbf16
--- /dev/null
+++ b/vcl/inc/vcl/FilterConfigItem.hxx
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#ifndef _FILTER_CONFIG_ITEM_HXX_
+#define _FILTER_CONFIG_ITEM_HXX_
+
+#include "svtools/svtdllapi.h"
+#include <tools/string.hxx>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/Any.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+
+class SVT_DLLPUBLIC FilterConfigItem
+{
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xUpdatableView;
+ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropSet;
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aFilterData;
+
+ sal_Bool bModified;
+
+ SVT_DLLPRIVATE sal_Bool ImplGetPropertyValue( ::com::sun::star::uno::Any& rAny,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& rXPropSet,
+ const ::rtl::OUString& rPropName,
+ sal_Bool bTestPropertyAvailability );
+
+ SVT_DLLPRIVATE void ImpInitTree( const String& rTree );
+
+
+ SVT_DLLPRIVATE static ::com::sun::star::beans::PropertyValue* GetPropertyValue(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rPropSeq,
+ const ::rtl::OUString& rName );
+ SVT_DLLPRIVATE static sal_Bool WritePropertyValue(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rPropSeq,
+ const ::com::sun::star::beans::PropertyValue& rPropValue );
+
+ public :
+
+ FilterConfigItem( const ::rtl::OUString& rSubTree );
+ FilterConfigItem( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData );
+ FilterConfigItem( const ::rtl::OUString& rSubTree, ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData );
+ ~FilterConfigItem();
+
+ // all read methods are trying to return values in following order:
+ // 1. FilterData PropertySequence
+ // 2. configuration
+ // 3. given default
+ sal_Bool ReadBool( const ::rtl::OUString& rKey, sal_Bool bDefault );
+ sal_Int32 ReadInt32( const ::rtl::OUString& rKey, sal_Int32 nDefault );
+ ::rtl::OUString
+ ReadString( const ::rtl::OUString& rKey, const ::rtl::OUString& rDefault );
+
+ // try to store to configuration
+ // and always stores into the FilterData sequence
+ void WriteBool( const ::rtl::OUString& rKey, sal_Bool bValue );
+ void WriteInt32( const ::rtl::OUString& rKey, sal_Int32 nValue );
+
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > GetFilterData() const;
+
+ // GetStatusIndicator is returning the "StatusIndicator" property of the FilterData sequence
+ ::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > GetStatusIndicator() const;
+};
+
+#endif // _FILTER_CONFIG_ITEM_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/vcl/graphicfilter.hxx b/vcl/inc/vcl/graphicfilter.hxx
new file mode 100644
index 000000000000..23d0c7204737
--- /dev/null
+++ b/vcl/inc/vcl/graphicfilter.hxx
@@ -0,0 +1,360 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _FILTER_HXX
+#define _FILTER_HXX
+
+#include <svtools/fltcall.hxx>
+#include "svtools/svtdllapi.h"
+#include <tools/stream.hxx>
+#include <vcl/graph.hxx>
+#include <tools/gen.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/field.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+struct WMF_EXTERNALHEADER;
+// -----------------------
+// - GraphicFilter-Types -
+// -----------------------
+
+struct ImplDirEntryHelper
+{
+ static sal_Bool Exists( const INetURLObject& rObj );
+ static void Kill( const String& rStr );
+};
+
+class Window;
+class Graphic;
+
+#define OPT_FILTERSECTION "Graphic"
+
+#define GRFILTER_OK 0
+#define GRFILTER_OPENERROR 1
+#define GRFILTER_IOERROR 2
+#define GRFILTER_FORMATERROR 3
+#define GRFILTER_VERSIONERROR 4
+#define GRFILTER_FILTERERROR 5
+#define GRFILTER_ABORT 6
+#define GRFILTER_TOOBIG 7
+
+#define GRFILTER_OUTHINT_GREY 1
+
+#define GRFILTER_FORMAT_NOTFOUND ((sal_uInt16)0xFFFF)
+#define GRFILTER_FORMAT_DONTKNOW ((sal_uInt16)0xFFFF)
+
+#define GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG 00000001
+#define GRFILTER_I_FLAGS_DONT_SET_LOGSIZE_FOR_JPEG 00000002
+#define GRFILTER_I_FLAGS_FOR_PREVIEW 00000004
+#define GRFILTER_I_FLAGS_ALLOW_PARTIAL_STREAMREAD 00000010
+
+#define IMP_BMP "SVBMP"
+#define IMP_SVMETAFILE "SVMETAFILE"
+#define IMP_WMF "SVWMF"
+#define IMP_EMF "SVEMF"
+#define IMP_SVSGF "SVSGF"
+#define IMP_SVSGV "SVSGV"
+#define IMP_GIF "SVIGIF"
+#define IMP_PNG "SVIPNG"
+#define IMP_JPEG "SVIJPEG"
+#define IMP_XBM "SVIXBM"
+#define IMP_XPM "SVIXPM"
+#define IMP_SVG "SVISVG"
+#define EXP_BMP "SVBMP"
+#define EXP_SVMETAFILE "SVMETAFILE"
+#define EXP_WMF "SVWMF"
+#define EXP_EMF "SVEMF"
+#define EXP_JPEG "SVEJPEG"
+#define EXP_SVG "SVESVG"
+#define EXP_PNG "SVEPNG"
+
+#define BMP_SHORTNAME "BMP"
+#define GIF_SHORTNAME "GIF"
+#define JPG_SHORTNAME "JPG"
+#define MET_SHORTNAME "MET"
+#define PCT_SHORTNAME "PCT"
+#define PNG_SHORTNAME "PNG"
+#define SVM_SHORTNAME "SVM"
+#define TIF_SHORTNAME "TIF"
+#define WMF_SHORTNAME "WMF"
+#define EMF_SHORTNAME "EMF"
+#define SVG_SHORTNAME "SVG"
+
+// ------------------------------------
+// - Info-Klasse fuer alle von uns
+// unterstuetzten Grafik-Fileformate
+// ------------------------------------
+
+#define GFF_NOT ( (sal_uInt16)0x0000 )
+#define GFF_BMP ( (sal_uInt16)0x0001 )
+#define GFF_GIF ( (sal_uInt16)0x0002 )
+#define GFF_JPG ( (sal_uInt16)0x0003 )
+#define GFF_PCD ( (sal_uInt16)0x0004 )
+#define GFF_PCX ( (sal_uInt16)0x0005 )
+#define GFF_PNG ( (sal_uInt16)0x0006 )
+#define GFF_TIF ( (sal_uInt16)0x0007 )
+#define GFF_XBM ( (sal_uInt16)0x0008 )
+#define GFF_XPM ( (sal_uInt16)0x0009 )
+#define GFF_PBM ( (sal_uInt16)0x000a )
+#define GFF_PGM ( (sal_uInt16)0x000b )
+#define GFF_PPM ( (sal_uInt16)0x000c )
+#define GFF_RAS ( (sal_uInt16)0x000d )
+#define GFF_TGA ( (sal_uInt16)0x000e )
+#define GFF_PSD ( (sal_uInt16)0x000f )
+#define GFF_EPS ( (sal_uInt16)0x0010 )
+#define GFF_DXF ( (sal_uInt16)0x00f1 )
+#define GFF_MET ( (sal_uInt16)0x00f2 )
+#define GFF_PCT ( (sal_uInt16)0x00f3 )
+#define GFF_SGF ( (sal_uInt16)0x00f4 )
+#define GFF_SVM ( (sal_uInt16)0x00f5 )
+#define GFF_WMF ( (sal_uInt16)0x00f6 )
+#define GFF_SGV ( (sal_uInt16)0x00f7 )
+#define GFF_EMF ( (sal_uInt16)0x00f8 )
+#define GFF_SVG ( (sal_uInt16)0x00f9 )
+#define GFF_XXX ( (sal_uInt16)0xffff )
+
+// ---------------------
+// - GraphicDescriptor -
+// ---------------------
+
+class SVT_DLLPUBLIC GraphicDescriptor
+{
+ SvStream* pFileStm;
+
+ String aPathExt;
+ Size aPixSize;
+ Size aLogSize;
+ sal_uInt16 nBitsPerPixel;
+ sal_uInt16 nPlanes;
+ sal_uInt16 nFormat;
+ sal_Bool bCompressed;
+ sal_Bool bOwnStream;
+
+ void ImpConstruct();
+
+ sal_Bool ImpDetectBMP( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectGIF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectJPG( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPCD( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPCX( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPNG( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectTIF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectXBM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectXPM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPBM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPGM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPPM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectRAS( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectTGA( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPSD( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectEPS( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectDXF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectMET( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectPCT( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectSGF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectSVM( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectWMF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectSGV( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectEMF( SvStream& rStm, sal_Bool bExtendedInfo );
+ sal_Bool ImpDetectSVG( SvStream& rStm, sal_Bool bExtendedInfo );
+ GraphicDescriptor( const GraphicDescriptor& );
+ GraphicDescriptor& operator=( const GraphicDescriptor& );
+
+public:
+
+ // Ctor, um einen Filenamen zu setzen. Es muss ::Detect() gerufen werden,
+ // um das File zu identifizieren;
+ // wenn das File keinen eindeutigen Header besitzt ( Mtf's ) wird das
+ // Format anhand der Extension bestimmt
+ GraphicDescriptor( const INetURLObject& rPath );
+
+ // Ctor, um einen Stream zu setzen. Es muss ::Detect() gerufen werden,
+ // um das File zu identifizieren;
+ // da einige Formate ( Mtf's ) keinen eindeutigen Header besitzen,
+ // ist es sinnvoll den Filenamen (inkl. Ext. ) mitanzugeben,
+ // da so das Format ueber die Extension ermittelt werden kann
+ GraphicDescriptor( SvStream& rInStream, const String* pPath = NULL );
+
+ // Dtor
+ virtual ~GraphicDescriptor();
+
+ // Startet die Detektion;
+ // bei bExtendedInfo == sal_True werden soweit wie moeglich
+ // Daten aus dem jeweiligen FileHeader ermittelt
+ // ( Groesse, Farbtiefe usw. )
+ virtual sal_Bool Detect( sal_Bool bExtendedInfo = sal_False );
+
+ // liefert das Fileformat nach erfolgreicher Detektion zurueck;
+ // wenn kein Format erkannt wurde, ist das Formart GFF_NOT
+ sal_uInt16 GetFileFormat() const { return nFormat; }
+
+ // liefert die Pixel-Bildgroesse oder 0-Size zurueck
+ const Size& GetSizePixel() const { return (Size&) aPixSize; }
+
+ // liefert die logische Bildgroesse in 1/100mm oder 0-Size zurueck
+ const Size& GetSize_100TH_MM() const { return (Size&) aLogSize; }
+
+ // liefert die Bits/Pixel oder 0 zurueck
+ sal_uInt16 GetBitsPerPixel() const { return nBitsPerPixel; }
+
+ // liefert die Anzahl der Planes oder 0 zurueck
+ sal_uInt16 GetPlanes() const { return nPlanes; }
+
+ // zeigt an, ob das Bild evtl. komprimiert (wie auch immer) ist
+ sal_Bool IsCompressed() const { return bCompressed; }
+
+ // gibt die Filternummer des Filters zurueck,
+ // der im GraphicFilter zum Lesen dieses Formats
+ // benoetigt wird
+ static String GetImportFormatShortName( sal_uInt16 nFormat );
+};
+
+// -----------------
+// - GraphicFilter -
+// -----------------
+
+struct FilterErrorEx
+{
+ sal_uLong nFilterError;
+ sal_uLong nStreamError;
+
+ FilterErrorEx() : nFilterError( 0UL ), nStreamError( 0UL ) {}
+};
+
+// -----------------------------------------------------------------------------
+
+struct ConvertData;
+class FilterConfigCache;
+class SVT_DLLPUBLIC GraphicFilter
+{
+ friend class SvFilterOptionsDialog;
+
+private:
+
+ void ImplInit();
+ sal_uLong ImplSetError( sal_uLong nError, const SvStream* pStm = NULL );
+ sal_uInt16 ImpTestOrFindFormat( const String& rPath, SvStream& rStream, sal_uInt16& rFormat );
+
+ DECL_LINK( FilterCallback, ConvertData* pData );
+
+protected:
+
+ rtl::OUString aFilterPath;
+ FilterConfigCache* pConfig;
+ FilterErrorEx* pErrorEx;
+ sal_Bool bAbort;
+ sal_Bool bUseConfig;
+ long nExpGraphHint;
+
+public:
+
+ GraphicFilter( sal_Bool bUseConfig = sal_True );
+ ~GraphicFilter();
+
+ void SetFilterPath( const rtl::OUString& rFilterPath ) { aFilterPath = rFilterPath; };
+
+ sal_uInt16 GetImportFormatCount();
+ sal_uInt16 GetImportFormatNumber( const String& rFormatName );
+ sal_uInt16 GetImportFormatNumberForMediaType( const String& rMediaType );
+ sal_uInt16 GetImportFormatNumberForShortName( const String& rShortName );
+ sal_uInt16 GetImportFormatNumberForTypeName( const String& rType );
+ String GetImportFormatName( sal_uInt16 nFormat );
+ String GetImportFormatTypeName( sal_uInt16 nFormat );
+ String GetImportFormatMediaType( sal_uInt16 nFormat );
+ String GetImportFormatShortName( sal_uInt16 nFormat );
+ String GetImportOSFileType( sal_uInt16 nFormat );
+ String GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry = 0 );
+ sal_Bool IsImportPixelFormat( sal_uInt16 nFormat );
+
+ sal_uInt16 GetExportFormatCount();
+ sal_uInt16 GetExportFormatNumber( const String& rFormatName );
+ sal_uInt16 GetExportFormatNumberForMediaType( const String& rShortName );
+ sal_uInt16 GetExportFormatNumberForShortName( const String& rShortName );
+ sal_uInt16 GetExportFormatNumberForTypeName( const String& rType );
+ String GetExportFormatName( sal_uInt16 nFormat );
+ String GetExportFormatTypeName( sal_uInt16 nFormat );
+ String GetExportFormatMediaType( sal_uInt16 nFormat );
+ String GetExportFormatShortName( sal_uInt16 nFormat );
+ String GetExportOSFileType( sal_uInt16 nFormat );
+ String GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry = 0 );
+ sal_Bool IsExportPixelFormat( sal_uInt16 nFormat );
+
+ sal_Bool HasExportDialog( sal_uInt16 nFormat );
+ sal_Bool DoExportDialog( Window* pWindow, sal_uInt16 nFormat );
+ sal_Bool DoExportDialog( Window* pWindow, sal_uInt16 nFormat, FieldUnit eFieldUnit );
+
+ sal_uInt16 ExportGraphic( const Graphic& rGraphic, const INetURLObject& rPath,
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData = NULL );
+ sal_uInt16 ExportGraphic( const Graphic& rGraphic, const String& rPath,
+ SvStream& rOStm, sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData = NULL );
+ long GetExportGraphicHint() const { return nExpGraphHint; }
+
+ sal_uInt16 CanImportGraphic( const INetURLObject& rPath,
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ sal_uInt16 * pDeterminedFormat = NULL);
+
+ sal_uInt16 ImportGraphic( Graphic& rGraphic, const INetURLObject& rPath,
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ sal_uInt16 * pDeterminedFormat = NULL, sal_uInt32 nImportFlags = 0 );
+
+ sal_uInt16 CanImportGraphic( const String& rPath, SvStream& rStream,
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ sal_uInt16 * pDeterminedFormat = NULL);
+
+ sal_uInt16 ImportGraphic( Graphic& rGraphic, const String& rPath,
+ SvStream& rStream,
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW,
+ sal_uInt16 * pDeterminedFormat = NULL, sal_uInt32 nImportFlags = 0,
+ WMF_EXTERNALHEADER *pExtHeader = NULL );
+
+ sal_uInt16 ImportGraphic( Graphic& rGraphic, const String& rPath,
+ SvStream& rStream,
+ sal_uInt16 nFormat,
+ sal_uInt16 * pDeterminedFormat, sal_uInt32 nImportFlags,
+ com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData,
+ WMF_EXTERNALHEADER *pExtHeader = NULL );
+
+ sal_Bool Setup( sal_uInt16 nFormat );
+
+ void Abort() { bAbort = sal_True; }
+
+ const FilterErrorEx& GetLastError() const;
+ void ResetLastError();
+
+ const Link GetFilterCallback() const;
+ static GraphicFilter& GetGraphicFilter();
+ static int LoadGraphic( const String& rPath, const String& rFilter,
+ Graphic& rGraphic,
+ GraphicFilter* pFilter = NULL,
+ sal_uInt16* pDeterminedFormat = NULL );
+};
+
+// ------------------------------------
+// - Windows Metafile Lesen/Schreiben -
+// ------------------------------------
+
+SVT_DLLPUBLIC sal_Bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF, FilterConfigItem* pConfigItem );
+SVT_DLLPUBLIC sal_Bool WriteWindowMetafileBits( SvStream& rStream, const GDIMetaFile& rMTF );
+
+#endif //_FILTER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/vcl/wmf.hxx b/vcl/inc/vcl/wmf.hxx
new file mode 100644
index 000000000000..66e2dcac589d
--- /dev/null
+++ b/vcl/inc/vcl/wmf.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _WMF_HXX
+#define _WMF_HXX
+
+#include "svtools/svtdllapi.h"
+#include <svtools/fltcall.hxx>
+
+struct WMF_EXTERNALHEADER
+{
+ sal_uInt16 xExt;
+ sal_uInt16 yExt;
+
+ /** One of the following values:
+ <ul>
+ <li>MM_TEXT</li>
+ <li>MM_LOMETRIC</li>
+ <li>MM_HIMETRIC</li>
+ <li>MM_LOENGLISH</li>
+ <li>MM_HIENGLISH</li>
+ <li>MM_TWIPS</li>
+ <li>MM_ISOTROPIC</li>
+ <li>MM_ANISOTROPIC</li>
+ </ul>
+ If this value is 0, then no external mapmode has been defined,
+ the internal one should then be used.
+ */
+ sal_uInt16 mapMode;
+
+ WMF_EXTERNALHEADER() :
+ xExt( 0 ),
+ yExt( 0 ),
+ mapMode( 0 )
+ {
+ }
+};
+
+sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem = NULL, WMF_EXTERNALHEADER *pExtHeader = NULL );
+
+SVT_DLLPUBLIC sal_Bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF, FilterConfigItem* pConfigItem );
+
+SVT_DLLPUBLIC sal_Bool ConvertGDIMetaFileToWMF( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pConfigItem = NULL, sal_Bool bPlaceable = sal_True );
+
+sal_Bool ConvertGDIMetaFileToEMF( const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pConfigItem = NULL );
+
+SVT_DLLPUBLIC sal_Bool WriteWindowMetafileBits( SvStream& rStream, const GDIMetaFile& rMTF );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/graphicfilter/data/README b/vcl/qa/cppunit/graphicfilter/data/README
new file mode 100644
index 000000000000..2cc9fb3cb58f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/README
@@ -0,0 +1,7 @@
+Files with the string 'CVE' in their name are encrypted to avoid
+problems with virus checkers on source code download.; use:
+
+mdecrypt --bare -a arcfour -o hex -k 435645 -s 3 foo.doc # to unencrypt
+mcrypt --bare -a arcfour -o hex -k 435645 -s 3 foo.doc # to create new tests
+
+to get access to the plain files for manual testing.
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore
new file mode 100644
index 000000000000..583b009c7c60
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.wmf-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2004-0691-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2004-0691-1.bmp
new file mode 100644
index 000000000000..d77db5782972
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2004-0691-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2006-0006-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2006-0006-1.bmp
new file mode 100644
index 000000000000..4cfbdfff8358
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2006-0006-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2007-2244-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2007-2244-1.bmp
new file mode 100644
index 000000000000..289cf8c0e964
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2007-2244-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2008-5870-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2008-5870-1.bmp
new file mode 100644
index 000000000000..d223dde288b5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/CVE-2008-5870-1.bmp
@@ -0,0 +1 @@
+ î¬.Gx©ŠKØ'seë2Ï~°Œè.G1Ì-”è‚#á›ø1†Y!ðÜÊ¢/ÙDVñ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp
new file mode 100644
index 000000000000..88b11ad57845
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/bmp/pass/EDB-22680-1.bmp
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf
new file mode 100644
index 000000000000..a511da43add5
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2004-0209-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf
new file mode 100644
index 000000000000..dd57d9102cd1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2008-1083-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf
new file mode 100644
index 000000000000..8fa6e9377938
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/fail/CVE-2009-1217-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf
new file mode 100644
index 000000000000..c71739a50b99
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-1087-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf
new file mode 100644
index 000000000000..746e85e847b4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/CVE-2008-2245-1.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf b/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf
new file mode 100644
index 000000000000..0af6c749bde4
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/emf/pass/fdo38580-3.emf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif
new file mode 100644
index 000000000000..7e84566e94b0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2007-3958-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif
new file mode 100644
index 000000000000..cbefd0162510
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/fail/CVE-2008-5937-1.gif
@@ -0,0 +1 @@
+””&‡VâusØ [eë21oæX \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif
new file mode 100644
index 000000000000..63426f9d80c2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2007-6715-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif
new file mode 100644
index 000000000000..e92a316e4b11
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2008-3013-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif
new file mode 100644
index 000000000000..190c7b0791a7
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2011-2131-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif
new file mode 100644
index 000000000000..cf4f30c21b91
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/CVE-2012-0282-1.gif
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif b/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif
new file mode 100644
index 000000000000..53d2ca01e854
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/gif/pass/EDB-19333-1.gif
@@ -0,0 +1 @@
+””&t©Š};'[ek2Ι~Ømé®ß1L-h£a[^¦Î.Þð!7¢/&»VOÊ»·BB^ïuËÃî±³È2k]Ynyå°G)‹Ê¿˜ð…‘jkš×Bà:Š’åå¢d#|åµÀu«\#ÑL—®í¢¡µê@Eßý˜ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-1.jpg
new file mode 100644
index 000000000000..3d9481aca908
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-4.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-4.jpg
new file mode 100644
index 000000000000..9d26db0050bb
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2004-0200-4.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg
new file mode 100644
index 000000000000..33bbe9b5f9e1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/fail/CVE-2008-5314-1.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg
new file mode 100644
index 000000000000..5eb27ffb5250
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-2.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg
new file mode 100644
index 000000000000..4917f207f35f
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-3.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg
new file mode 100644
index 000000000000..bc668d3e3f31
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/jpg/pass/CVE-2004-0200-5.jpg
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png
new file mode 100644
index 000000000000..fa90a296f9fa
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2004-0597-1.png
@@ -0,0 +1,3 @@
+Àœë#Mb£Š}ÕÔo7ë2ÎË~X¨á.^TÿwBè„!õ›žf1±°ƒÿ»±sé ‘tšùgšça2bA±Õð‡ÁËHbè—"8àî|†ìeGf­S$N0nI€Öªõ
+Ôç0"ð—JG°zÀ¤Ü¢(s?d)À"Ëÿ‘GE¢×F¯–9~}–ÇrÕ TÎp?áÅÂ*¿ìò·¥ckµ$E"ŒXï¯8á¾=2±T_3³v¿™#é –á$Hh4«‰JÑKiÝŠJÿ&7r…ú€…Ï=uŠ¯ù69KÙjãûäÎçèÿëWh{‘é½Ï$· dVÅÜ[îÐЖ™Êy\à%Žº%†Ç¾H® meÛÃÞ+ “Á}€ÀgXI¡2ñ>‰*Ä«õ&ù˜Õú›Í· )†Ì¸6ÔpU‚TjODhÙ¶1™éù-ÄÔ<WµŒUR±Kø591Òþ¦«M“„?
+~˜æ*Nr¡Ìu;µãÀkh©ÉXˆÔà{ÖßÔ¤»' Ów©ìF[—ÛÒKèRÓf§y›‹O¹¨%0´©iháx׃‹€wz¿4dT.¥@ŒXm4¦Þi¤íô÷pçð¬Z¼¾^±ßy‘˜ÝÂЯú`®ºÎ_YŸ¬? …t‹uw4\kÁd¬J~m˜‹gú`<2ìl²Ñn¦ÒãùÞ*ð òök h*n÷„w7ƒ‘!“YIßP+hK†Ø*Ôž`õ?Ëâç˜ü \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png
new file mode 100644
index 000000000000..d0644d139749
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2005-0633-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png
new file mode 100644
index 000000000000..9b30cc38c7db
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2006-7210-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png
new file mode 100644
index 000000000000..b9ff67bb8b81
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2007-2365-1.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png
new file mode 100644
index 000000000000..592fda10aa9e
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2009-1511-1.png
@@ -0,0 +1 @@
+Àœë#Mb£Š}ÕÔo7ë2Í~\íá._舄Ã{ÜÚß'p|&êFàà¨/û§§‚ô¬ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png
new file mode 100644
index 000000000000..cbba93bedd81
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/png/pass/black.png
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/sgv/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/sgv/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/sgv/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/sgv/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/sgv/indeterminate/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/sgv/indeterminate/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/sgv/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/sgv/pass/SaveAsPicture.sgv b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/SaveAsPicture.sgv
new file mode 100755
index 000000000000..0fe908e91c98
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/SaveAsPicture.sgv
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/sgv/pass/faxpfeil.sgv b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/faxpfeil.sgv
new file mode 100755
index 000000000000..c8317c62e152
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/sgv/pass/faxpfeil.sgv
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676 b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676
new file mode 100644
index 000000000000..49d3ddf28b02
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2123-1.wmf-0.009-676
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf
new file mode 100644
index 000000000000..ac546ce5b14c
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-2124-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf
new file mode 100644
index 000000000000..aab34004e927
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2005-4560-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf
new file mode 100644
index 000000000000..b68b7403c338
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-1.wmf
@@ -0,0 +1 @@
+HUÛ¬.DZ©Š|Ød[eë2Ë~Sïb&[1Ì-kèÀg¥ßÚ"uZJjÞë<í‘êweƒù»·üÿâŠÏÂî±¼ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf
new file mode 100644
index 000000000000..370abe0e249d
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/fail/CVE-2006-0143-2.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore
new file mode 100644
index 000000000000..583b009c7c60
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/indeterminate/.gitignore
@@ -0,0 +1 @@
+*.wmf-*
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/.gitignore
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf
new file mode 100644
index 000000000000..e70664e64aa0
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2005-2123-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf
new file mode 100644
index 000000000000..cdb09c6b21e2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2006-4071-1.wmf
@@ -0,0 +1 @@
+HUÛ¬.DZ©Š¡üI2ÆwÉ~¤ïé._1Ì-œè„#™žf1.!Þ0¢/Ù¸T¸ÊDH½½¡NÏÂî±¼ \ No newline at end of file
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf
new file mode 100644
index 000000000000..7864da572ca2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1090-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1238-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1238-1.wmf
new file mode 100644
index 000000000000..10da32742570
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1238-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1245-1.wmf b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1245-1.wmf
new file mode 100644
index 000000000000..10da32742570
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/data/wmf/pass/CVE-2007-1245-1.wmf
Binary files differ
diff --git a/vcl/qa/cppunit/graphicfilter/filters-test.cxx b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
new file mode 100644
index 000000000000..bdf8269575e2
--- /dev/null
+++ b/vcl/qa/cppunit/graphicfilter/filters-test.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Initial Developer of the Original Code is
+ * Caolán McNamara <caolanm@redhat.com>
+ * Portions created by the Initial Developer are Copyright (C) 2011 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Caolán McNamara <caolanm@redhat.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#include <unotest/filters-test.hxx>
+#include <test/bootstrapfixture.hxx>
+
+#include <osl/file.hxx>
+#include <osl/process.h>
+
+#include <svtools/filter.hxx>
+
+using namespace ::com::sun::star;
+
+/* Implementation of Filters test */
+
+class SvtoolsFiltersTest
+ : public test::FiltersTest
+ , public test::BootstrapFixture
+{
+public:
+ SvtoolsFiltersTest() : BootstrapFixture(true, false) {}
+
+ virtual bool load(const rtl::OUString &,
+ const rtl::OUString &rURL, const rtl::OUString &,
+ unsigned int, unsigned int, unsigned int);
+
+ /**
+ * Ensure CVEs remain unbroken
+ */
+ void testCVEs();
+
+ CPPUNIT_TEST_SUITE(SvtoolsFiltersTest);
+ CPPUNIT_TEST(testCVEs);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+bool SvtoolsFiltersTest::load(const rtl::OUString &,
+ const rtl::OUString &rURL, const rtl::OUString &,
+ unsigned int, unsigned int, unsigned int)
+{
+ GraphicFilter aGraphicFilter(false);
+ SvFileStream aFileStream(rURL, STREAM_READ);
+ Graphic aGraphic;
+ return aGraphicFilter.ImportGraphic(aGraphic, rURL, aFileStream) == 0;
+}
+
+void SvtoolsFiltersTest::testCVEs()
+{
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/wmf/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/emf/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/sgv/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/png/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/jpg/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/gif/"),
+ rtl::OUString());
+
+ testDir(rtl::OUString(),
+ getURLFromSrc("/svtools/qa/cppunit/data/bmp/"),
+ rtl::OUString());
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SvtoolsFiltersTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/FilterConfigCache.cxx b/vcl/source/filter/FilterConfigCache.cxx
new file mode 100644
index 000000000000..dc4b7c740cdf
--- /dev/null
+++ b/vcl/source/filter/FilterConfigCache.cxx
@@ -0,0 +1,561 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "FilterConfigCache.hxx"
+#include <svtools/filter.hxx>
+#include <com/sun/star/uno/Any.h>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/uno/Exception.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+
+using namespace ::com::sun::star::lang ; // XMultiServiceFactory
+using namespace ::com::sun::star::container ; // XNameAccess
+using namespace ::com::sun::star::uno ; // Reference
+using namespace ::com::sun::star::beans ; // PropertyValue
+using namespace ::com::sun::star::configuration ;
+using ::rtl::OUString;
+
+const char* FilterConfigCache::FilterConfigCacheEntry::InternalPixelFilterNameList[] =
+{
+ IMP_BMP, IMP_GIF, IMP_PNG,IMP_JPEG, IMP_XBM, IMP_XPM,
+ EXP_BMP, EXP_JPEG, EXP_PNG, NULL
+};
+
+const char* FilterConfigCache::FilterConfigCacheEntry::InternalVectorFilterNameList[] =
+{
+ IMP_SVMETAFILE, IMP_WMF, IMP_EMF, IMP_SVSGF, IMP_SVSGV, IMP_SVG,
+ EXP_SVMETAFILE, EXP_WMF, EXP_EMF, EXP_SVG, NULL
+};
+
+const char* FilterConfigCache::FilterConfigCacheEntry::ExternalPixelFilterNameList[] =
+{
+ "egi", "icd", "ipd", "ipx", "ipb", "epb", "epg",
+ "epp", "ira", "era", "itg", "iti", "eti", "exp", NULL
+};
+
+sal_Bool FilterConfigCache::bInitialized = sal_False;
+sal_Int32 FilterConfigCache::nIndType = -1;
+sal_Int32 FilterConfigCache::nIndUIName = -1;
+sal_Int32 FilterConfigCache::nIndDocumentService = -1;
+sal_Int32 FilterConfigCache::nIndFilterService = -1;
+sal_Int32 FilterConfigCache::nIndFlags = -1;
+sal_Int32 FilterConfigCache::nIndUserData = -1;
+sal_Int32 FilterConfigCache::nIndFileFormatVersion = -1;
+sal_Int32 FilterConfigCache::nIndTemplateName = -1;
+
+sal_Bool FilterConfigCache::FilterConfigCacheEntry::CreateFilterName( const OUString& rUserDataEntry )
+{
+ bIsPixelFormat = bIsInternalFilter = sal_False;
+ sFilterName = String( rUserDataEntry );
+ const char** pPtr;
+ for ( pPtr = InternalPixelFilterNameList; *pPtr && ( bIsInternalFilter == sal_False ); pPtr++ )
+ {
+ if ( sFilterName.EqualsIgnoreCaseAscii( *pPtr ) )
+ {
+ bIsInternalFilter = sal_True;
+ bIsPixelFormat = sal_True;
+ }
+ }
+ for ( pPtr = InternalVectorFilterNameList; *pPtr && ( bIsInternalFilter == sal_False ); pPtr++ )
+ {
+ if ( sFilterName.EqualsIgnoreCaseAscii( *pPtr ) )
+ bIsInternalFilter = sal_True;
+ }
+ if ( !bIsInternalFilter )
+ {
+ for ( pPtr = ExternalPixelFilterNameList; *pPtr && ( bIsPixelFormat == sal_False ); pPtr++ )
+ {
+ if ( sFilterName.EqualsIgnoreCaseAscii( *pPtr ) )
+ bIsPixelFormat = sal_True;
+ }
+ rtl::OUString sTemp(SVLIBRARY("?"));
+ sal_Int32 nIndex = sTemp.indexOf(static_cast<sal_Unicode>('?'));
+ sFilterName = sTemp.replaceAt(nIndex, 1, sFilterName);
+ }
+ return sFilterName.Len() != 0;
+}
+
+String FilterConfigCache::FilterConfigCacheEntry::GetShortName()
+{
+ String aShortName;
+ if ( lExtensionList.getLength() )
+ {
+ aShortName = lExtensionList[ 0 ];
+ if ( aShortName.SearchAscii( "*.", 0 ) == 0 )
+ aShortName.Erase( 0, 2 );
+ }
+ return aShortName;
+}
+
+/** helper to open the configuration root of the underlying
+ config package
+
+ @param sPackage
+ specify, which config package should be opened.
+ Must be one of "types" or "filters"
+
+ @return A valid object if open was successfull. The access on opened
+ data will be readonly. It returns NULL in case open failed.
+
+ @throws It let pass RuntimeExceptions only.
+ */
+Reference< XInterface > openConfig(const char* sPackage)
+ throw(RuntimeException)
+{
+ Reference< XComponentContext > xContext(
+ comphelper::getProcessComponentContext() );
+ Reference< XInterface > xCfg;
+ try
+ {
+ // get access to config API (not to file!)
+ Reference< XMultiServiceFactory > xConfigProvider = theDefaultProvider::get( xContext );
+
+ Sequence< Any > lParams(1);
+ PropertyValue aParam ;
+
+ // define cfg path for open
+ aParam.Name = OUString( "nodepath" );
+ if (rtl_str_compareIgnoreAsciiCase(sPackage, "types") == 0)
+ aParam.Value <<= OUString( "/org.openoffice.TypeDetection.Types/Types" );
+ if (rtl_str_compareIgnoreAsciiCase(sPackage, "filters") == 0)
+ aParam.Value <<= OUString( "/org.openoffice.TypeDetection.GraphicFilter/Filters" );
+ lParams[0] = makeAny(aParam);
+
+ // get access to file
+ xCfg = xConfigProvider->createInstanceWithArguments(
+ OUString( "com.sun.star.configuration.ConfigurationAccess" ), lParams);
+ }
+ catch(const RuntimeException&)
+ { throw; }
+ catch(const Exception&)
+ { xCfg.clear(); }
+
+ return xCfg;
+}
+
+void FilterConfigCache::ImplInit()
+{
+ OUString STYPE ( "Type" );
+ OUString SUINAME ( "UIName" );
+ OUString SUICOMPONENT ( "UIComponent" );
+ OUString SFLAGS ( "Flags" );
+ OUString SMEDIATYPE ( "MediaType" );
+ OUString SEXTENSIONS ( "Extensions" );
+ OUString SFORMATNAME ( "FormatName" );
+ OUString SREALFILTERNAME ( "RealFilterName" );
+
+ // get access to config
+ Reference< XNameAccess > xTypeAccess ( openConfig("types" ), UNO_QUERY );
+ Reference< XNameAccess > xFilterAccess( openConfig("filters"), UNO_QUERY );
+
+ if ( xTypeAccess.is() && xFilterAccess.is() )
+ {
+ Sequence< OUString > lAllFilter = xFilterAccess->getElementNames();
+ sal_Int32 nAllFilterCount = lAllFilter.getLength();
+
+ for ( sal_Int32 i = 0; i < nAllFilterCount; i++ )
+ {
+ OUString sInternalFilterName = lAllFilter[ i ];
+ Reference< XPropertySet > xFilterSet;
+ xFilterAccess->getByName( sInternalFilterName ) >>= xFilterSet;
+ if (!xFilterSet.is())
+ continue;
+
+ FilterConfigCacheEntry aEntry;
+
+ aEntry.sInternalFilterName = sInternalFilterName;
+ xFilterSet->getPropertyValue(STYPE) >>= aEntry.sType;
+ xFilterSet->getPropertyValue(SUINAME) >>= aEntry.sUIName;
+ xFilterSet->getPropertyValue(SREALFILTERNAME) >>= aEntry.sFilterType;
+ Sequence< OUString > lFlags;
+ xFilterSet->getPropertyValue(SFLAGS) >>= lFlags;
+ if (lFlags.getLength()!=1 || lFlags[0].isEmpty())
+ continue;
+ if (lFlags[0].equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("import")))
+ aEntry.nFlags = 1;
+ else
+ if (lFlags[0].equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("export")))
+ aEntry.nFlags = 2;
+
+ OUString sUIComponent;
+ xFilterSet->getPropertyValue(SUICOMPONENT) >>= sUIComponent;
+ aEntry.bHasDialog = sUIComponent.getLength();
+
+ ::rtl::OUString sFormatName;
+ xFilterSet->getPropertyValue(SFORMATNAME) >>= sFormatName;
+ aEntry.CreateFilterName( sFormatName );
+
+ Reference< XPropertySet > xTypeSet;
+ xTypeAccess->getByName( aEntry.sType ) >>= xTypeSet;
+ if (!xTypeSet.is())
+ continue;
+
+ xTypeSet->getPropertyValue(SMEDIATYPE) >>= aEntry.sMediaType;
+ xTypeSet->getPropertyValue(SEXTENSIONS) >>= aEntry.lExtensionList;
+
+ // The first extension will be used
+ // to generate our internal FilterType ( BMP, WMF ... )
+ String aExtension( aEntry.GetShortName() );
+ if (aExtension.Len() != 3)
+ continue;
+
+ if ( aEntry.nFlags & 1 )
+ aImport.push_back( aEntry );
+ if ( aEntry.nFlags & 2 )
+ aExport.push_back( aEntry );
+
+ // bFilterEntryCreated!?
+ if (!( aEntry.nFlags & 3 ))
+ continue; //? Entry was already inserted ... but following code will be supressed?!
+ }
+ }
+};
+
+const char* FilterConfigCache::InternalFilterListForSvxLight[] =
+{
+ "bmp","1","SVBMP",
+ "bmp","2","SVBMP",
+ "dxf","1","idx",
+ "eps","1","ips",
+ "eps","2","eps",
+ "gif","1","SVIGIF",
+ "gif","2","egi",
+ "jpg","1","SVIJPEG",
+ "jpg","2","SVEJPEG",
+ "sgv","1","SVSGV",
+ "sgf","1","SVSGF",
+ "met","1","ime",
+ "met","2","eme",
+ "png","1","SVIPNG",
+ "png","2","SVEPNG",
+ "pct","1","ipt",
+ "pct","2","ept",
+ "pcd","1","icd",
+ "psd","1","ipd",
+ "pcx","1","ipx",
+ "pbm","1","ipb",
+ "pbm","2","epb",
+ "pgm","1","ipb",
+ "pgm","2","epg",
+ "ppm","1","ipb",
+ "ppm","2","epp",
+ "ras","1","ira",
+ "ras","2","era",
+ "svm","1","SVMETAFILE",
+ "svm","2","SVMETAFILE",
+ "tga","1","itg",
+ "tif","1","iti",
+ "tif","2","eti",
+ "emf","1","SVEMF",
+ "emf","2","SVEMF",
+ "wmf","1","SVWMF",
+ "wmf","2","SVWMF",
+ "xbm","1","SVIXBM",
+ "xpm","1","SVIXPM",
+ "xpm","2","exp",
+ "svg","1","SVISVG",
+ "svg","2","SVESVG",
+ NULL
+};
+
+void FilterConfigCache::ImplInitSmart()
+{
+ const char** pPtr;
+ for ( pPtr = InternalFilterListForSvxLight; *pPtr; pPtr++ )
+ {
+ FilterConfigCacheEntry aEntry;
+
+ OUString sExtension( OUString::createFromAscii( *pPtr++ ) );
+
+ aEntry.lExtensionList.realloc( 1 );
+ aEntry.lExtensionList[ 0 ] = sExtension;
+
+ aEntry.sType = sExtension;
+ aEntry.sUIName = sExtension;
+
+ rtl::OString sFlags( *pPtr++ );
+ aEntry.nFlags = sFlags.toInt32();
+
+ OUString sUserData( OUString::createFromAscii( *pPtr ) );
+ aEntry.CreateFilterName( sUserData );
+
+ if ( aEntry.nFlags & 1 )
+ aImport.push_back( aEntry );
+ if ( aEntry.nFlags & 2 )
+ aExport.push_back( aEntry );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+FilterConfigCache::FilterConfigCache( sal_Bool bConfig ) :
+ bUseConfig ( bConfig )
+{
+ if ( bUseConfig )
+ ImplInit();
+ else
+ ImplInitSmart();
+}
+
+FilterConfigCache::~FilterConfigCache()
+{
+}
+
+String FilterConfigCache::GetImportFilterName( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].sFilterName;
+ return String::EmptyString();
+}
+
+sal_uInt16 FilterConfigCache::GetImportFormatNumber( const String& rFormatName )
+{
+ CacheVector::iterator aIter( aImport.begin() );
+ while ( aIter != aImport.end() )
+ {
+ if ( aIter->sUIName.equalsIgnoreAsciiCase( rFormatName ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aImport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aImport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetImportFormatNumberForMediaType( const String& rMediaType )
+{
+ CacheVector::iterator aIter( aImport.begin() );
+ while ( aIter != aImport.end() )
+ {
+ if ( aIter->sMediaType.equalsIgnoreAsciiCase( rMediaType ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aImport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aImport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetImportFormatNumberForShortName( const String& rShortName )
+{
+ CacheVector::iterator aIter( aImport.begin() );
+ while ( aIter != aImport.end() )
+ {
+ if ( aIter->GetShortName().EqualsIgnoreCaseAscii( rShortName ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aImport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aImport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetImportFormatNumberForTypeName( const String& rType )
+{
+ CacheVector::iterator aIter( aImport.begin() );
+ while ( aIter != aImport.end() )
+ {
+ if ( aIter->sType.equalsIgnoreAsciiCase( rType ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aImport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aImport.begin());
+}
+
+String FilterConfigCache::GetImportFormatName( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].sUIName;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportFormatMediaType( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].sMediaType;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportFormatShortName( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].GetShortName();
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ if ( (nFormat < aImport.size()) && (nEntry < aImport[ nFormat ].lExtensionList.getLength()) )
+ return aImport[ nFormat ].lExtensionList[ nEntry ];
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportFilterType( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].sType;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportFilterTypeName( sal_uInt16 nFormat )
+{
+ if( nFormat < aImport.size() )
+ return aImport[ nFormat ].sFilterType;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ String aWildcard( GetImportFormatExtension( nFormat, nEntry ) );
+ if ( aWildcard.Len() )
+ aWildcard.Insert( rtl::OUString("*."), 0 );
+ return aWildcard;
+}
+
+sal_Bool FilterConfigCache::IsImportInternalFilter( sal_uInt16 nFormat )
+{
+ return (nFormat < aImport.size()) && aImport[ nFormat ].bIsInternalFilter;
+}
+
+sal_Bool FilterConfigCache::IsImportPixelFormat( sal_uInt16 nFormat )
+{
+ return (nFormat < aImport.size()) && aImport[ nFormat ].bIsPixelFormat;
+}
+
+// ------------------------------------------------------------------------
+
+String FilterConfigCache::GetExportFilterName( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].sFilterName;
+ return String::EmptyString();
+}
+
+sal_uInt16 FilterConfigCache::GetExportFormatNumber( const String& rFormatName )
+{
+ CacheVector::iterator aIter( aExport.begin() );
+ while ( aIter != aExport.end() )
+ {
+ if ( aIter->sUIName.equalsIgnoreAsciiCase( rFormatName ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aExport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aExport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetExportFormatNumberForMediaType( const String& rMediaType )
+{
+ CacheVector::iterator aIter( aExport.begin() );
+ while ( aIter != aExport.end() )
+ {
+ if ( aIter->sMediaType.equalsIgnoreAsciiCase( rMediaType ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aExport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aExport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetExportFormatNumberForShortName( const String& rShortName )
+{
+ CacheVector::iterator aIter( aExport.begin() );
+ while ( aIter != aExport.end() )
+ {
+ if ( aIter->GetShortName().EqualsIgnoreCaseAscii( rShortName ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aExport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aExport.begin());
+}
+
+sal_uInt16 FilterConfigCache::GetExportFormatNumberForTypeName( const String& rType )
+{
+ CacheVector::iterator aIter( aExport.begin() );
+ while ( aIter != aExport.end() )
+ {
+ if ( aIter->sType.equalsIgnoreAsciiCase( rType ) )
+ break;
+ aIter++;
+ }
+ return sal::static_int_cast< sal_uInt16 >(aIter == aExport.end() ? GRFILTER_FORMAT_NOTFOUND : aIter - aExport.begin());
+}
+
+String FilterConfigCache::GetExportFormatName( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].sUIName;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportFormatMediaType( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].sMediaType;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportFormatShortName( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].GetShortName();
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ if ( (nFormat < aExport.size()) && (nEntry < aExport[ nFormat ].lExtensionList.getLength()) )
+ return aExport[ nFormat ].lExtensionList[ nEntry ];
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportFilterTypeName( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].sFilterType;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportInternalFilterName( sal_uInt16 nFormat )
+{
+ if( nFormat < aExport.size() )
+ return aExport[ nFormat ].sInternalFilterName;
+ return String::EmptyString();
+}
+
+String FilterConfigCache::GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ String aWildcard( GetExportFormatExtension( nFormat, nEntry ) );
+ if ( aWildcard.Len() )
+ aWildcard.Insert( rtl::OUString("*."), 0 );
+ return aWildcard;
+}
+
+sal_Bool FilterConfigCache::IsExportInternalFilter( sal_uInt16 nFormat )
+{
+ return (nFormat < aExport.size()) && aExport[ nFormat ].bIsInternalFilter;
+}
+
+sal_Bool FilterConfigCache::IsExportPixelFormat( sal_uInt16 nFormat )
+{
+ return (nFormat < aExport.size()) && aExport[ nFormat ].bIsPixelFormat;
+}
+
+sal_Bool FilterConfigCache::IsExportDialog( sal_uInt16 nFormat )
+{
+ return (nFormat < aExport.size()) && aExport[ nFormat ].bHasDialog;
+}
+
+// ------------------------------------------------------------------------
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/FilterConfigCache.hxx b/vcl/source/filter/FilterConfigCache.hxx
new file mode 100644
index 000000000000..b3f0022b05bb
--- /dev/null
+++ b/vcl/source/filter/FilterConfigCache.hxx
@@ -0,0 +1,131 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _FILTER_CONFIG_CACHE_HXX_
+#define _FILTER_CONFIG_CACHE_HXX_
+
+#include <tools/string.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+
+#include <vector>
+
+class FilterConfigCache
+{
+ struct FilterConfigCacheEntry
+ {
+ ::rtl::OUString sInternalFilterName;
+ ::rtl::OUString sType;
+ ::com::sun::star::uno::Sequence< ::rtl::OUString > lExtensionList;
+ ::rtl::OUString sUIName;
+ ::rtl::OUString sDocumentService;
+ ::rtl::OUString sFilterService;
+ ::rtl::OUString sTemplateName;
+
+ ::rtl::OUString sMediaType;
+ ::rtl::OUString sFilterType;
+
+ sal_Int32 nFlags;
+ sal_Int32 nFileFormatVersion;
+
+ // user data
+ String sFilterName;
+ sal_Bool bHasDialog : 1;
+ sal_Bool bIsInternalFilter : 1;
+ sal_Bool bIsPixelFormat : 1;
+
+ sal_Bool CreateFilterName( const ::rtl::OUString& rUserDataEntry );
+ String GetShortName( );
+
+ static const char* InternalPixelFilterNameList[];
+ static const char* InternalVectorFilterNameList[];
+ static const char* ExternalPixelFilterNameList[];
+ };
+
+ typedef std::vector< FilterConfigCacheEntry > CacheVector;
+
+
+ CacheVector aImport;
+ CacheVector aExport;
+ sal_Bool bUseConfig;
+
+ static sal_Bool bInitialized;
+ static sal_Int32 nIndType;
+ static sal_Int32 nIndUIName;
+ static sal_Int32 nIndDocumentService;
+ static sal_Int32 nIndFilterService;
+ static sal_Int32 nIndFlags;
+ static sal_Int32 nIndUserData;
+ static sal_Int32 nIndFileFormatVersion;
+ static sal_Int32 nIndTemplateName;
+
+ static const char* InternalFilterListForSvxLight[];
+
+ void ImplInit();
+ void ImplInitSmart();
+
+ public :
+
+ sal_uInt16 GetImportFormatCount() const
+ { return sal::static_int_cast< sal_uInt16 >(aImport.size()); };
+ sal_uInt16 GetImportFormatNumber( const String& rFormatName );
+ sal_uInt16 GetImportFormatNumberForMediaType( const String& rMediaType );
+ sal_uInt16 GetImportFormatNumberForShortName( const String& rShortName );
+ sal_uInt16 GetImportFormatNumberForTypeName( const String& rType );
+ String GetImportFilterName( sal_uInt16 nFormat );
+ String GetImportFormatName( sal_uInt16 nFormat );
+ String GetImportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry = 0);
+ String GetImportFormatMediaType( sal_uInt16 nFormat );
+ String GetImportFormatShortName( sal_uInt16 nFormat );
+ String GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry );
+ String GetImportFilterType( sal_uInt16 nFormat );
+ String GetImportFilterTypeName( sal_uInt16 nFormat );
+
+ sal_Bool IsImportInternalFilter( sal_uInt16 nFormat );
+ sal_Bool IsImportPixelFormat( sal_uInt16 nFormat );
+
+ sal_uInt16 GetExportFormatCount() const
+ { return sal::static_int_cast< sal_uInt16 >(aExport.size()); };
+ sal_uInt16 GetExportFormatNumber( const String& rFormatName );
+ sal_uInt16 GetExportFormatNumberForMediaType( const String& rMediaType );
+ sal_uInt16 GetExportFormatNumberForShortName( const String& rShortName );
+ sal_uInt16 GetExportFormatNumberForTypeName( const String& rType );
+ String GetExportFilterName( sal_uInt16 nFormat );
+ String GetExportFormatName( sal_uInt16 nFormat );
+ String GetExportFormatExtension( sal_uInt16 nFormat, sal_Int32 nEntry = 0 );
+ String GetExportFormatMediaType( sal_uInt16 nFormat );
+ String GetExportFormatShortName( sal_uInt16 nFormat );
+ String GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry );
+ String GetExportFilterTypeName( sal_uInt16 nFormat );
+ String GetExportInternalFilterName( sal_uInt16 nFormat );
+
+ sal_Bool IsExportInternalFilter( sal_uInt16 nFormat );
+ sal_Bool IsExportPixelFormat( sal_uInt16 nFormat );
+ sal_Bool IsExportDialog( sal_uInt16 nFormat );
+
+ FilterConfigCache( sal_Bool bUseConfig );
+ ~FilterConfigCache();
+
+};
+
+#endif // _FILTER_CONFIG_CACHE_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/FilterConfigItem.cxx b/vcl/source/filter/FilterConfigItem.cxx
new file mode 100644
index 000000000000..91310b367bed
--- /dev/null
+++ b/vcl/source/filter/FilterConfigItem.cxx
@@ -0,0 +1,439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svtools/FilterConfigItem.hxx>
+
+#include <unotools/configmgr.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+
+using ::rtl::OUString;
+using namespace ::utl ; // getProcessServiceFactory
+using namespace ::com::sun::star::lang ; // XMultiServiceFactory
+using namespace ::com::sun::star::beans ; // PropertyValue
+using namespace ::com::sun::star::uno ; // Reference
+using namespace ::com::sun::star::util ; // XChangesBatch
+using namespace ::com::sun::star::awt ; // Size
+using namespace ::com::sun::star::container ; //
+using namespace ::com::sun::star::configuration; //
+using namespace ::com::sun::star::task ; // XStatusIndicator
+
+static sal_Bool ImpIsTreeAvailable( Reference< XMultiServiceFactory >& rXCfgProv, const rtl::OUString& rTree )
+{
+ sal_Bool bAvailable = !rTree.isEmpty();
+ if ( bAvailable )
+ {
+ using comphelper::string::getTokenCount;
+ using comphelper::string::getToken;
+
+ sal_Int32 nTokenCount = getTokenCount(rTree, '/');
+ sal_Int32 i = 0;
+
+ if ( rTree[0] == '/' )
+ ++i;
+ if ( rTree[rTree.getLength() - 1] == '/' )
+ --nTokenCount;
+
+ Any aAny;
+ aAny <<= getToken(rTree, i++, '/');
+
+ // creation arguments: nodepath
+ PropertyValue aPathArgument;
+ aPathArgument.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
+ aPathArgument.Value = aAny;
+
+ Sequence< Any > aArguments( 1 );
+ aArguments[ 0 ] <<= aPathArgument;
+
+ Reference< XInterface > xReadAccess;
+ try
+ {
+ xReadAccess = rXCfgProv->createInstanceWithArguments(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) ),
+ aArguments );
+ }
+ catch (const ::com::sun::star::uno::Exception&)
+ {
+ bAvailable = sal_False;
+ }
+ if ( xReadAccess.is() )
+ {
+ for ( ; bAvailable && ( i < nTokenCount ); i++ )
+ {
+ Reference< XHierarchicalNameAccess > xHierarchicalNameAccess
+ ( xReadAccess, UNO_QUERY );
+
+ if ( !xHierarchicalNameAccess.is() )
+ bAvailable = sal_False;
+ else
+ {
+ rtl::OUString aNode( getToken(rTree, i, '/') );
+ if ( !xHierarchicalNameAccess->hasByHierarchicalName( aNode ) )
+ bAvailable = sal_False;
+ else
+ {
+ Any a( xHierarchicalNameAccess->getByHierarchicalName( aNode ) );
+ try
+ {
+ a >>= xReadAccess;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ bAvailable = sal_False;
+ }
+ }
+ }
+ }
+ }
+ }
+ return bAvailable;
+}
+
+void FilterConfigItem::ImpInitTree( const String& rSubTree )
+{
+ bModified = sal_False;
+
+ Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
+
+ Reference< XMultiServiceFactory > xCfgProv = theDefaultProvider::get( xContext );
+
+ OUString sTree(
+ OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.")) +
+ rSubTree);
+ if ( ImpIsTreeAvailable(xCfgProv, sTree) )
+ {
+ Any aAny;
+ // creation arguments: nodepath
+ PropertyValue aPathArgument;
+ aAny <<= sTree;
+ aPathArgument.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
+ aPathArgument.Value = aAny;
+
+ // creation arguments: commit mode
+ PropertyValue aModeArgument;
+ sal_Bool bAsyncron = sal_True;
+ aAny <<= bAsyncron;
+ aModeArgument.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "lazywrite" ) );
+ aModeArgument.Value = aAny;
+
+ Sequence< Any > aArguments( 2 );
+ aArguments[ 0 ] <<= aPathArgument;
+ aArguments[ 1 ] <<= aModeArgument;
+
+ try
+ {
+ xUpdatableView = xCfgProv->createInstanceWithArguments(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
+ aArguments );
+ if ( xUpdatableView.is() )
+ xPropSet = Reference< XPropertySet >( xUpdatableView, UNO_QUERY );
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ OSL_FAIL( "FilterConfigItem::FilterConfigItem - Could not access configuration Key" );
+ }
+ }
+}
+
+FilterConfigItem::FilterConfigItem( const OUString& rSubTree )
+{
+ ImpInitTree( rSubTree );
+}
+
+FilterConfigItem::FilterConfigItem( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData )
+{
+ if ( pFilterData )
+ aFilterData = *pFilterData;
+}
+
+FilterConfigItem::FilterConfigItem( const OUString& rSubTree,
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData )
+{
+ ImpInitTree( rSubTree );
+
+ if ( pFilterData )
+ aFilterData = *pFilterData;
+};
+
+FilterConfigItem::~FilterConfigItem()
+{
+ if ( xUpdatableView.is() )
+ {
+ if ( xPropSet.is() && bModified )
+ {
+ Reference< XChangesBatch > xUpdateControl( xUpdatableView, UNO_QUERY );
+ if ( xUpdateControl.is() )
+ {
+ try
+ {
+ xUpdateControl->commitChanges();
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ OSL_FAIL( "FilterConfigItem::FilterConfigItem - Could not update configuration data" );
+ }
+ }
+ }
+ }
+}
+
+sal_Bool FilterConfigItem::ImplGetPropertyValue( Any& rAny, const Reference< XPropertySet >& rXPropSet, const OUString& rString, sal_Bool bTestPropertyAvailability )
+{
+ sal_Bool bRetValue = sal_True;
+
+ if ( rXPropSet.is() )
+ {
+ if ( bTestPropertyAvailability )
+ {
+ bRetValue = sal_False;
+ try
+ {
+ Reference< XPropertySetInfo >
+ aXPropSetInfo( rXPropSet->getPropertySetInfo() );
+ if ( aXPropSetInfo.is() )
+ bRetValue = aXPropSetInfo->hasPropertyByName( rString );
+ }
+ catch( ::com::sun::star::uno::Exception& )
+ {
+ //
+ }
+ }
+ if ( bRetValue )
+ {
+ try
+ {
+ rAny = rXPropSet->getPropertyValue( rString );
+ if ( !rAny.hasValue() )
+ bRetValue = sal_False;
+ }
+ catch( ::com::sun::star::uno::Exception& )
+ {
+ bRetValue = sal_False;
+ }
+ }
+ }
+ else
+ bRetValue = sal_False;
+ return bRetValue;
+}
+
+
+// if property is available it returns a pointer,
+// otherwise the result is null
+PropertyValue* FilterConfigItem::GetPropertyValue( Sequence< PropertyValue >& rPropSeq, const OUString& rName )
+{
+ PropertyValue* pPropValue = NULL;
+
+ sal_Int32 i, nCount;
+ for ( i = 0, nCount = rPropSeq.getLength(); i < nCount; i++ )
+ {
+ if ( rPropSeq[ i ].Name == rName )
+ {
+ pPropValue = &rPropSeq[ i ];
+ break;
+ }
+ }
+ return pPropValue;
+}
+
+/* if PropertySequence already includes a PropertyValue using the same name, the
+ corresponding PropertyValue is replaced, otherwise the given PropertyValue
+ will be appended */
+
+sal_Bool FilterConfigItem::WritePropertyValue( Sequence< PropertyValue >& rPropSeq, const PropertyValue& rPropValue )
+{
+ sal_Bool bRet = sal_False;
+ if ( !rPropValue.Name.isEmpty() )
+ {
+ sal_Int32 i, nCount;
+ for ( i = 0, nCount = rPropSeq.getLength(); i < nCount; i++ )
+ {
+ if ( rPropSeq[ i ].Name == rPropValue.Name )
+ break;
+ }
+ if ( i == nCount )
+ rPropSeq.realloc( ++nCount );
+
+ rPropSeq[ i ] = rPropValue;
+
+ bRet = sal_True;
+ }
+ return bRet;
+}
+
+sal_Bool FilterConfigItem::ReadBool( const OUString& rKey, sal_Bool bDefault )
+{
+ Any aAny;
+ sal_Bool bRetValue = bDefault;
+ PropertyValue* pPropVal = GetPropertyValue( aFilterData, rKey );
+ if ( pPropVal )
+ {
+ pPropVal->Value >>= bRetValue;
+ }
+ else if ( ImplGetPropertyValue( aAny, xPropSet, rKey, sal_True ) )
+ {
+ aAny >>= bRetValue;
+ }
+ PropertyValue aBool;
+ aBool.Name = rKey;
+ aBool.Value <<= bRetValue;
+ WritePropertyValue( aFilterData, aBool );
+ return bRetValue;
+}
+
+sal_Int32 FilterConfigItem::ReadInt32( const OUString& rKey, sal_Int32 nDefault )
+{
+ Any aAny;
+ sal_Int32 nRetValue = nDefault;
+ PropertyValue* pPropVal = GetPropertyValue( aFilterData, rKey );
+ if ( pPropVal )
+ {
+ pPropVal->Value >>= nRetValue;
+ }
+ else if ( ImplGetPropertyValue( aAny, xPropSet, rKey, sal_True ) )
+ {
+ aAny >>= nRetValue;
+ }
+ PropertyValue aInt32;
+ aInt32.Name = rKey;
+ aInt32.Value <<= nRetValue;
+ WritePropertyValue( aFilterData, aInt32 );
+ return nRetValue;
+}
+
+OUString FilterConfigItem::ReadString( const OUString& rKey, const OUString& rDefault )
+{
+ Any aAny;
+ OUString aRetValue( rDefault );
+ PropertyValue* pPropVal = GetPropertyValue( aFilterData, rKey );
+ if ( pPropVal )
+ {
+ pPropVal->Value >>= aRetValue;
+ }
+ else if ( ImplGetPropertyValue( aAny, xPropSet, rKey, sal_True ) )
+ {
+ aAny >>= aRetValue;
+ }
+ PropertyValue aString;
+ aString.Name = rKey;
+ aString.Value <<= aRetValue;
+ WritePropertyValue( aFilterData, aString );
+ return aRetValue;
+}
+
+void FilterConfigItem::WriteBool( const OUString& rKey, sal_Bool bNewValue )
+{
+ PropertyValue aBool;
+ aBool.Name = rKey;
+ aBool.Value <<= bNewValue;
+ WritePropertyValue( aFilterData, aBool );
+
+ if ( xPropSet.is() )
+ {
+ Any aAny;
+ if ( ImplGetPropertyValue( aAny, xPropSet, rKey, sal_True ) )
+ {
+ sal_Bool bOldValue(sal_True);
+ if ( aAny >>= bOldValue )
+ {
+ if ( bOldValue != bNewValue )
+ {
+ aAny <<= bNewValue;
+ try
+ {
+ xPropSet->setPropertyValue( rKey, aAny );
+ bModified = sal_True;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ OSL_FAIL( "FilterConfigItem::WriteBool - could not set PropertyValue" );
+ }
+ }
+ }
+ }
+ }
+}
+
+void FilterConfigItem::WriteInt32( const OUString& rKey, sal_Int32 nNewValue )
+{
+ PropertyValue aInt32;
+ aInt32.Name = rKey;
+ aInt32.Value <<= nNewValue;
+ WritePropertyValue( aFilterData, aInt32 );
+
+ if ( xPropSet.is() )
+ {
+ Any aAny;
+
+ if ( ImplGetPropertyValue( aAny, xPropSet, rKey, sal_True ) )
+ {
+ sal_Int32 nOldValue = 0;
+ if ( aAny >>= nOldValue )
+ {
+ if ( nOldValue != nNewValue )
+ {
+ aAny <<= nNewValue;
+ try
+ {
+ xPropSet->setPropertyValue( rKey, aAny );
+ bModified = sal_True;
+ }
+ catch ( ::com::sun::star::uno::Exception& )
+ {
+ OSL_FAIL( "FilterConfigItem::WriteInt32 - could not set PropertyValue" );
+ }
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Sequence< PropertyValue > FilterConfigItem::GetFilterData() const
+{
+ return aFilterData;
+}
+
+// ------------------------------------------------------------------------
+
+Reference< XStatusIndicator > FilterConfigItem::GetStatusIndicator() const
+{
+ Reference< XStatusIndicator > xStatusIndicator;
+ const rtl::OUString sStatusIndicator( RTL_CONSTASCII_USTRINGPARAM( "StatusIndicator" ) );
+
+ sal_Int32 i, nCount = aFilterData.getLength();
+ for ( i = 0; i < nCount; i++ )
+ {
+ if ( aFilterData[ i ].Name == sStatusIndicator )
+ {
+ aFilterData[ i ].Value >>= xStatusIndicator;
+ break;
+ }
+ }
+ return xStatusIndicator;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
new file mode 100644
index 000000000000..4839dfa1cc44
--- /dev/null
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -0,0 +1,2449 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/mutex.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <ucbhelper/content.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/salctype.hxx>
+#include <vcl/pngread.hxx>
+#include <vcl/pngwrite.hxx>
+#include <vcl/svgdata.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <osl/file.hxx>
+#include <svtools/filter.hxx>
+#include "FilterConfigCache.hxx"
+#include <svtools/FilterConfigItem.hxx>
+#include <svtools/fltcall.hxx>
+#include <svtools/wmf.hxx>
+#include "gifread.hxx"
+#include "jpeg.hxx"
+#include "xbmread.hxx"
+#include "xpmread.hxx"
+#include <svl/solar.hrc>
+#include <svtools/svtools.hrc>
+#include "sgffilt.hxx"
+#include "osl/module.hxx"
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/uno/XWeak.hpp>
+#include <com/sun/star/uno/XAggregation.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/svg/XSVGWriter.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/ucb/CommandAbortedException.hpp>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/localfilehelper.hxx>
+#include <rtl/bootstrap.hxx>
+#include <rtl/instance.hxx>
+#include <rtl/logfile.hxx>
+#include <vcl/metaact.hxx>
+#include <vector>
+
+#include "SvFilterOptionsDialog.hxx"
+
+#define PMGCHUNG_msOG 0x6d734f47 // Microsoft Office Animated GIF
+
+#define IMPORT_FUNCTION_NAME "GraphicImport"
+#define EXPORT_FUNCTION_NAME "GraphicExport"
+
+// -----------
+// - statics -
+// -----------
+
+using namespace ::rtl;
+using namespace ::com::sun::star;
+
+using comphelper::string::getTokenCount;
+using comphelper::string::getToken;
+
+typedef ::std::vector< GraphicFilter* > FilterList_impl;
+static FilterList_impl* pFilterHdlList = NULL;
+
+static ::osl::Mutex& getListMutex()
+{
+ static ::osl::Mutex s_aListProtection;
+ return s_aListProtection;
+}
+
+// -------------------------
+// - ImpFilterOutputStream -
+// -------------------------
+
+class ImpFilterOutputStream : public ::cppu::WeakImplHelper1< ::com::sun::star::io::XOutputStream >
+{
+protected:
+
+ SvStream& mrStm;
+
+ virtual void SAL_CALL writeBytes( const ::com::sun::star::uno::Sequence< sal_Int8 >& rData ) throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException) { mrStm.Write( rData.getConstArray(), rData.getLength() ); }
+ 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) { mrStm.Flush(); }
+ virtual void SAL_CALL closeOutput() throw() {}
+
+public:
+
+ ImpFilterOutputStream( SvStream& rStm ) : mrStm( rStm ) {}
+ ~ImpFilterOutputStream() {}
+};
+
+sal_Bool ImplDirEntryHelper::Exists( const INetURLObject& rObj )
+{
+ sal_Bool bExists = sal_False;
+
+ try
+ {
+ ::ucbhelper::Content aCnt( rObj.GetMainURL( INetURLObject::NO_DECODE ),
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
+ comphelper::getProcessComponentContext() );
+
+ bExists = aCnt.isDocument();
+ }
+ catch(const ::com::sun::star::ucb::CommandAbortedException&)
+ {
+ SAL_WARN( "svtools.filter", "CommandAbortedException" );
+ }
+ catch(const ::com::sun::star::ucb::ContentCreationException&)
+ {
+ SAL_WARN( "svtools.filter", "ContentCreationException" );
+ }
+ catch( ... )
+ {
+ SAL_WARN( "svtools.filter", "Any other exception" );
+ }
+ return bExists;
+}
+
+// -----------------------------------------------------------------------------
+
+void ImplDirEntryHelper::Kill( const String& rMainUrl )
+{
+ try
+ {
+ ::ucbhelper::Content aCnt( rMainUrl,
+ ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >(),
+ comphelper::getProcessComponentContext() );
+
+ aCnt.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" )),
+ ::com::sun::star::uno::makeAny( sal_Bool( sal_True ) ) );
+ }
+ catch(const ::com::sun::star::ucb::CommandAbortedException&)
+ {
+ SAL_WARN( "svtools.filter", "CommandAbortedException" );
+ }
+ catch( ... )
+ {
+ SAL_WARN( "svtools.filter", "Any other exception" );
+ }
+}
+
+// --------------------
+// - Helper functions -
+// --------------------
+
+//--------------------------------------------------------------------------
+
+sal_uInt8* ImplSearchEntry( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nComp, sal_uLong nSize )
+{
+ while ( nComp-- >= nSize )
+ {
+ sal_uLong i;
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
+ break;
+ }
+ if ( i == nSize )
+ return pSource;
+ pSource++;
+ }
+ return NULL;
+}
+
+//--------------------------------------------------------------------------
+
+inline String ImpGetExtension( const String &rPath )
+{
+ String aExt;
+ INetURLObject aURL( rPath );
+ aExt = aURL.GetFileExtension().toAsciiUpperCase();
+ return aExt;
+}
+
+bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen)
+{
+ sal_uInt8 sBuf[3];
+ // store number format
+ sal_uInt16 oldNumberFormat = rStream.GetNumberFormatInt();
+ sal_uInt32 nOffset; // in ms documents the pict format is used without the first 512 bytes
+ for ( nOffset = 0; ( nOffset <= 512 ) && ( ( nStreamPos + nOffset + 14 ) <= nStreamLen ); nOffset += 512 )
+ {
+ short y1,x1,y2,x2;
+ sal_Bool bdBoxOk = sal_True;
+
+ rStream.Seek( nStreamPos + nOffset);
+ // size of the pict in version 1 pict ( 2bytes) : ignored
+ rStream.SeekRel(2);
+ // bounding box (bytes 2 -> 9)
+ rStream.SetNumberFormatInt(NUMBERFORMAT_INT_BIGENDIAN);
+ rStream >> y1 >> x1 >> y2 >> x2;
+ rStream.SetNumberFormatInt(oldNumberFormat); // reset format
+
+ if (x1 > x2 || y1 > y2 || // bad bdbox
+ (x1 == x2 && y1 == y2) || // 1 pixel picture
+ x2-x1 > 2048 || y2-y1 > 2048 ) // picture anormaly big
+ bdBoxOk = sal_False;
+
+ // read version op
+ rStream.Read( sBuf,3 );
+ // see http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Imaging_With_QuickDraw/Appendix_A.pdf
+ // normal version 2 - page A23 and A24
+ if ( sBuf[ 0 ] == 0x00 && sBuf[ 1 ] == 0x11 && sBuf[ 2 ] == 0x02)
+ return true;
+ // normal version 1 - page A25
+ else if (sBuf[ 0 ] == 0x11 && sBuf[ 1 ] == 0x01 && bdBoxOk)
+ return true;
+ }
+ return false;
+}
+
+
+/*************************************************************************
+|*
+|* ImpPeekGraphicFormat()
+|*
+|* Beschreibung:
+|* Diese Funktion kann zweierlei:
+|* 1.) Datei anlesen, Dateiformat ermitteln
+|* Eingabe-prarameter:
+|* rPath - Dateipfad
+|* rFormatExtension - Inhalt egal
+|* bTest - setze sal_False
+|* Ausgabe-parameter:
+|* Funkionswert - sal_True wenn Erfolg
+|* rFormatExtension - Bei Erfolg: uebliche Dateiendung
+|* des Formats (Grossbuchstaben)
+|* 2.) Datei anlesen, Dateiformat ueberpruefen
+|* Eingabe-prarameter:
+|* rPath - Dateipfad
+|* rFormatExtension - uebliche Dateiendung des Formats
+|* (Grossbuchstaben)
+|* bTest - setze sal_True
+|* Ausgabe-parameter:
+|* Funkionswert - sal_False, wenn die Datei bestimmt nicht
+|* vom uebgebenen Format ist.
+|* sal_True, wenn die Datei WAHRSCHEINLICH von
+|* dem Format ist, ODER WENN DAS FORMAT
+|* DIESER FUNKTION NICHT BEKANNT IST!
+|*
+*************************************************************************/
+
+static sal_Bool ImpPeekGraphicFormat( SvStream& rStream, String& rFormatExtension, sal_Bool bTest )
+{
+ sal_uInt16 i;
+ sal_uInt8 sFirstBytes[ 256 ];
+ sal_uLong nFirstLong,nSecondLong;
+ sal_uLong nStreamPos = rStream.Tell();
+
+ rStream.Seek( STREAM_SEEK_TO_END );
+ sal_uLong nStreamLen = rStream.Tell() - nStreamPos;
+ rStream.Seek( nStreamPos );
+
+ if ( !nStreamLen )
+ {
+ SvLockBytes* pLockBytes = rStream.GetLockBytes();
+ if ( pLockBytes )
+ pLockBytes->SetSynchronMode( sal_True );
+
+ rStream.Seek( STREAM_SEEK_TO_END );
+ nStreamLen = rStream.Tell() - nStreamPos;
+ rStream.Seek( nStreamPos );
+ }
+ if (!nStreamLen)
+ {
+ return false; // this prevents at least a STL assertion
+ }
+ else if (nStreamLen >= 256)
+ { // load first 256 bytes into a buffer
+ rStream.Read( sFirstBytes, 256 );
+ }
+ else
+ {
+ rStream.Read( sFirstBytes, nStreamLen );
+
+ for( i = (sal_uInt16) nStreamLen; i < 256; i++ )
+ sFirstBytes[ i ]=0;
+ }
+
+ if( rStream.GetError() )
+ return sal_False;
+
+ // Die ersten 8 Bytes in nFirstLong, nSecondLong unterbringen,
+ // Big-Endian:
+ for( i = 0, nFirstLong = 0L, nSecondLong = 0L; i < 4; i++ )
+ {
+ nFirstLong=(nFirstLong<<8)|(sal_uLong)sFirstBytes[i];
+ nSecondLong=(nSecondLong<<8)|(sal_uLong)sFirstBytes[i+4];
+ }
+
+ // Folgende Variable ist nur bei bTest==sal_True interessant. Sie
+ // bleibt sal_False, wenn das Format (rFormatExtension) hier noch nicht
+ // einprogrammiert wurde.
+ sal_Bool bSomethingTested = sal_False;
+
+ // Nun werden die verschieden Formate ueberprueft. Dabei ist die
+ // Reihenfolge nicht egal. Z.b. koennte eine MET-Datei auch durch
+ // den BMP-Test gehen, umgekehrt kann eine BMP-Datei kaum durch den
+ // MET-Test gehen. Also sollte MET vor BMP getestet werden.
+ // Theoretisch waere aber vielleicht auch eine BMP-Datei denkbar,
+ // die durch den MET-Test geht.
+ // Diese Probleme gibt es natuerlich nicht nur bei MET und BMP.
+ // Deshalb wird im Falle der Uberpruefung eines Formats (bTest==sal_True)
+ // nur genau dieses eine Format getestet. Alles andere koennte fatale
+ // Folgen haben, z.B. wenn der Benutzer sagt, es sei BMP-Datei (und es
+ // ist BMP-Datei), und hier wuerde die Datei durch den MET-Test gehen...
+
+ //--------------------------- MET ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "MET", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if( sFirstBytes[2] == 0xd3 )
+ {
+ rStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStream.Seek( nStreamPos );
+ sal_uInt16 nFieldSize;
+ sal_uInt8 nMagic;
+ sal_Bool bOK=sal_True;
+ rStream >> nFieldSize >> nMagic;
+ for (i=0; i<3; i++) {
+ if (nFieldSize<6) { bOK=sal_False; break; }
+ if (nStreamLen < rStream.Tell() + nFieldSize ) { bOK=sal_False; break; }
+ rStream.SeekRel(nFieldSize-3);
+ rStream >> nFieldSize >> nMagic;
+ if (nMagic!=0xd3) { bOK=sal_False; break; }
+ }
+ rStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ if (bOK && !rStream.GetError()) {
+ rFormatExtension = rtl::OUString("MET");
+ return sal_True;
+ }
+ }
+ }
+
+ //--------------------------- BMP ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "BMP", 3 ) == COMPARE_EQUAL ) )
+ {
+ sal_uInt8 nOffs;
+
+ bSomethingTested=sal_True;
+
+ // OS/2-Bitmaparray ('BA') koennen wir evtl. auch lesen,
+ // dementspr. muessen wir den Offset anpassen,
+ // um auf die erste Bitmap im Array zu stossen
+ if ( sFirstBytes[0] == 0x42 && sFirstBytes[1] == 0x41 )
+ nOffs = 14;
+ else
+ nOffs = 0;
+
+ // Jetzt testen wir zunaechst auf 'BM'
+ if ( sFirstBytes[0+nOffs]==0x42 && sFirstBytes[1+nOffs]==0x4d )
+ {
+ // unter OS/2 koennen die Reserved-Flags != 0 sein
+ // (was sie eigentlich nicht duerften);
+ // in diesem Fall testen wir die Groesse des BmpInfoHeaders
+ if ( ( sFirstBytes[6+nOffs]==0x00 &&
+ sFirstBytes[7+nOffs]==0x00 &&
+ sFirstBytes[8+nOffs]==0x00 &&
+ sFirstBytes[9+nOffs]==0x00 ) ||
+ sFirstBytes[14+nOffs] == 0x28 ||
+ sFirstBytes[14+nOffs] == 0x0c )
+ {
+ rFormatExtension = rtl::OUString("BMP");
+ return sal_True;
+ }
+ }
+ }
+
+ //--------------------------- WMF/EMF ------------------------------------
+
+ if( !bTest ||
+ ( rFormatExtension.CompareToAscii( "WMF", 3 ) == COMPARE_EQUAL ) ||
+ ( rFormatExtension.CompareToAscii( "EMF", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+
+ if ( nFirstLong==0xd7cdc69a || nFirstLong==0x01000900 )
+ {
+ rFormatExtension = rtl::OUString("WMF");
+ return sal_True;
+ }
+ else if( nFirstLong == 0x01000000 && sFirstBytes[ 40 ] == 0x20 && sFirstBytes[ 41 ] == 0x45 &&
+ sFirstBytes[ 42 ] == 0x4d && sFirstBytes[ 43 ] == 0x46 )
+ {
+ rFormatExtension = rtl::OUString("EMF");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- PCX ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "PCX", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if (sFirstBytes[0]==0x0a)
+ {
+ sal_uInt8 nVersion=sFirstBytes[1];
+ sal_uInt8 nEncoding=sFirstBytes[2];
+ if( ( nVersion==0 || nVersion==2 || nVersion==3 || nVersion==5 ) && nEncoding<=1 )
+ {
+ rFormatExtension = rtl::OUString("PCX");
+ return sal_True;
+ }
+ }
+ }
+
+ //--------------------------- TIF ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "TIF", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if ( nFirstLong==0x49492a00 || nFirstLong==0x4d4d002a )
+ {
+ rFormatExtension = rtl::OUString("TIF");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- GIF ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "GIF", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if ( nFirstLong==0x47494638 && (sFirstBytes[4]==0x37 || sFirstBytes[4]==0x39) && sFirstBytes[5]==0x61 )
+ {
+ rFormatExtension = rtl::OUString("GIF");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- PNG ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "PNG", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if (nFirstLong==0x89504e47 && nSecondLong==0x0d0a1a0a)
+ {
+ rFormatExtension = rtl::OUString("PNG");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- JPG ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "JPG", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if ( ( nFirstLong==0xffd8ffe0 && sFirstBytes[6]==0x4a && sFirstBytes[7]==0x46 && sFirstBytes[8]==0x49 && sFirstBytes[9]==0x46 ) ||
+ ( nFirstLong==0xffd8fffe ) || ( 0xffd8ff00 == ( nFirstLong & 0xffffff00 ) ) )
+ {
+ rFormatExtension = rtl::OUString("JPG");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- SVM ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "SVM", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if( nFirstLong==0x53564744 && sFirstBytes[4]==0x49 )
+ {
+ rFormatExtension = rtl::OUString("SVM");
+ return sal_True;
+ }
+ else if( sFirstBytes[0]==0x56 && sFirstBytes[1]==0x43 && sFirstBytes[2]==0x4C &&
+ sFirstBytes[3]==0x4D && sFirstBytes[4]==0x54 && sFirstBytes[5]==0x46 )
+ {
+ rFormatExtension = rtl::OUString("SVM");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- PCD ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "PCD", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+ if( nStreamLen >= 2055 )
+ {
+ char sBuf[8];
+ rStream.Seek( nStreamPos + 2048 );
+ rStream.Read( sBuf, 7 );
+
+ if( strncmp( sBuf, "PCD_IPI", 7 ) == 0 )
+ {
+ rFormatExtension = rtl::OUString("PCD");
+ return sal_True;
+ }
+ }
+ }
+
+ //--------------------------- PSD ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "PSD", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+ if ( ( nFirstLong == 0x38425053 ) && ( (nSecondLong >> 16 ) == 1 ) )
+ {
+ rFormatExtension = rtl::OUString("PSD");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- EPS ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "EPS", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+ if ( ( nFirstLong == 0xC5D0D3C6 ) || ( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"%!PS-Adobe", 10, 10 ) &&
+ ImplSearchEntry( &sFirstBytes[15], (sal_uInt8*)"EPS", 3, 3 ) ) )
+ {
+ rFormatExtension = rtl::OUString("EPS");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- DXF ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "DXF", 3 ) == COMPARE_EQUAL ) )
+ {
+ //Binary DXF File Format
+ if( strncmp( (const char*) sFirstBytes, "AutoCAD Binary DXF", 18 ) == 0 )
+ {
+ rFormatExtension = rtl::OUString("DXF");
+ return sal_True;
+ }
+
+ //ASCII DXF File Format
+ i=0;
+ while (i<256 && sFirstBytes[i]<=32)
+ ++i;
+
+ if (i<256 && sFirstBytes[i]=='0')
+ {
+ ++i;
+
+ //only now do we have sufficient data to make a judgement
+ //based on a '0' + 'SECTION' == DXF argument
+ bSomethingTested=sal_True;
+
+ while( i<256 && sFirstBytes[i]<=32 )
+ ++i;
+
+ if (i+7<256 && (strncmp((const char*)(sFirstBytes+i),"SECTION",7)==0))
+ {
+ rFormatExtension = rtl::OUString("DXF");
+ return sal_True;
+ }
+ }
+
+ }
+
+ //--------------------------- PCT ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "PCT", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+ if (isPCT(rStream, nStreamPos, nStreamLen))
+ {
+ rFormatExtension = rtl::OUString("PCT");
+ return sal_True;
+ }
+ }
+
+ //------------------------- PBM + PGM + PPM ---------------------------
+ if( !bTest ||
+ ( rFormatExtension.CompareToAscii( "PBM", 3 ) == COMPARE_EQUAL ) ||
+ ( rFormatExtension.CompareToAscii( "PGM", 3 ) == COMPARE_EQUAL ) ||
+ ( rFormatExtension.CompareToAscii( "PPM", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if ( sFirstBytes[ 0 ] == 'P' )
+ {
+ switch( sFirstBytes[ 1 ] )
+ {
+ case '1' :
+ case '4' :
+ rFormatExtension = rtl::OUString("PBM");
+ return sal_True;
+
+ case '2' :
+ case '5' :
+ rFormatExtension = rtl::OUString("PGM");
+ return sal_True;
+
+ case '3' :
+ case '6' :
+ rFormatExtension = rtl::OUString("PPM");
+ return sal_True;
+ }
+ }
+ }
+
+ //--------------------------- RAS( SUN RasterFile )------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "RAS", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if( nFirstLong == 0x59a66a95 )
+ {
+ rFormatExtension = rtl::OUString("RAS");
+ return sal_True;
+ }
+ }
+
+ //--------------------------- XPM ------------------------------------
+ if( !bTest )
+ {
+ bSomethingTested = sal_True;
+ if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"/* XPM */", 256, 9 ) )
+ {
+ rFormatExtension = rtl::OUString("XPM");
+ return sal_True;
+ }
+ }
+ else if( rFormatExtension.CompareToAscii( "XPM", 3 ) == COMPARE_EQUAL )
+ {
+ bSomethingTested = sal_True;
+ return sal_True;
+ }
+
+ //--------------------------- XBM ------------------------------------
+ if( !bTest )
+ {
+ sal_uLong nSize = ( nStreamLen > 2048 ) ? 2048 : nStreamLen;
+ sal_uInt8* pBuf = new sal_uInt8 [ nSize ];
+
+ rStream.Seek( nStreamPos );
+ rStream.Read( pBuf, nSize );
+ sal_uInt8* pPtr = ImplSearchEntry( pBuf, (sal_uInt8*)"#define", nSize, 7 );
+
+ if( pPtr )
+ {
+ if( ImplSearchEntry( pPtr, (sal_uInt8*)"_width", pBuf + nSize - pPtr, 6 ) )
+ {
+ rFormatExtension = rtl::OUString("XBM");
+ delete[] pBuf;
+ return sal_True;
+ }
+ }
+ delete[] pBuf;
+ }
+ else if( rFormatExtension.CompareToAscii( "XBM", 3 ) == COMPARE_EQUAL )
+ {
+ bSomethingTested = sal_True;
+ return sal_True;
+ }
+
+ //--------------------------- SVG ------------------------------------
+ if( !bTest )
+ {
+ // check for Xml
+ if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<?xml", 256, 5 ) // is it xml
+ && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"version", 256, 7 )) // does it have a version (required for xml)
+ {
+ bool bIsSvg(false);
+
+ // check for DOCTYPE svg combination
+ if( ImplSearchEntry( sFirstBytes, (sal_uInt8*)"DOCTYPE", 256, 7 ) // 'DOCTYPE' is there
+ && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"svg", 256, 3 )) // 'svg' is there
+ {
+ bIsSvg = true;
+ }
+
+ // check for svg element in 1st 256 bytes
+ if(!bIsSvg && ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
+ {
+ bIsSvg = true;
+ }
+
+ if(!bIsSvg)
+ {
+ // it's a xml, look for '<svg' in full file. Should not happen too
+ // often since the tests above will handle most cases, but can happen
+ // with Svg files containing big comment headers or Svg as the host
+ // language
+ const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
+ sal_uInt8* pBuf = new sal_uInt8[nSize];
+
+ rStream.Seek(nStreamPos);
+ rStream.Read(pBuf, nSize);
+
+ if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
+ {
+ bIsSvg = true;
+ }
+
+ delete[] pBuf;
+ }
+
+ if(bIsSvg)
+ {
+ rFormatExtension = OUString( "SVG" );
+ return sal_True;
+ }
+ }
+ else
+ {
+ // #119176# Svg files which have no xml header at all have shown up,
+ // detect those, too
+ bool bIsSvg(false);
+
+ // check for svg element in 1st 256 bytes
+ if(ImplSearchEntry( sFirstBytes, (sal_uInt8*)"<svg", 256, 4 )) // '<svg'
+ {
+ bIsSvg = true;
+ }
+
+ if(!bIsSvg)
+ {
+ // look for '<svg' in full file. Should not happen too
+ // often since the tests above will handle most cases, but can happen
+ // with Svg files containing big comment headers or Svg as the host
+ // language
+ const sal_uLong nSize((nStreamLen > 2048) ? 2048 : nStreamLen);
+ sal_uInt8* pBuf = new sal_uInt8[nSize];
+
+ rStream.Seek(nStreamPos);
+ rStream.Read(pBuf, nSize);
+
+ if(ImplSearchEntry(pBuf, (sal_uInt8*)"<svg", nSize, 4)) // '<svg'
+ {
+ bIsSvg = true;
+ }
+
+ delete[] pBuf;
+ }
+
+ if(bIsSvg)
+ {
+ rFormatExtension = OUString( "SVG" );
+ return sal_True;
+ }
+ }
+ }
+ else if( rFormatExtension.CompareToAscii( "SVG", 3 ) == COMPARE_EQUAL )
+ {
+ bSomethingTested = sal_True;
+ return sal_True;
+ }
+
+ //--------------------------- TGA ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "TGA", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+
+ // just a simple test for the extension
+ if( rFormatExtension.CompareToAscii( "TGA", 3 ) == COMPARE_EQUAL )
+ return sal_True;
+ }
+
+ //--------------------------- SGV ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "SGV", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested = sal_True;
+
+ // just a simple test for the extension
+ if( rFormatExtension.CompareToAscii( "SGV", 3 ) == COMPARE_EQUAL )
+ return sal_True;
+ }
+
+ //--------------------------- SGF ------------------------------------
+ if( !bTest || ( rFormatExtension.CompareToAscii( "SGF", 3 ) == COMPARE_EQUAL ) )
+ {
+ bSomethingTested=sal_True;
+ if( sFirstBytes[ 0 ] == 'J' && sFirstBytes[ 1 ] == 'J' )
+ {
+ rFormatExtension = rtl::OUString("SGF");
+ return sal_True;
+ }
+ }
+
+ return bTest && !bSomethingTested;
+}
+
+//--------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::ImpTestOrFindFormat( const String& rPath, SvStream& rStream, sal_uInt16& rFormat )
+{
+ sal_uInt16 n = pConfig->GetImportFormatCount();
+
+ // ggf. Filter bzw. Format durch anlesen ermitteln,
+ // oder durch anlesen zusichern, dass das Format stimmt:
+ if( rFormat == GRFILTER_FORMAT_DONTKNOW )
+ {
+ String aFormatExt;
+ if( ImpPeekGraphicFormat( rStream, aFormatExt, sal_False ) )
+ {
+ for( sal_uInt16 i = 0; i < n; i++ )
+ {
+ if( pConfig->GetImportFormatExtension( i ).EqualsIgnoreCaseAscii( aFormatExt ) )
+ {
+ rFormat = i;
+ return GRFILTER_OK;
+ }
+ }
+ }
+ // ggf. Filter anhand der Datei-Endung raussuchen:
+ if( rPath.Len() )
+ {
+ String aExt( ImpGetExtension( rPath ) );
+ for( sal_uInt16 i = 0; i < n; i++ )
+ {
+ if( pConfig->GetImportFormatExtension( i ).EqualsIgnoreCaseAscii( aExt ) )
+ {
+ rFormat = i;
+ return GRFILTER_OK;
+ }
+ }
+ }
+ return GRFILTER_FORMATERROR;
+ }
+ else
+ {
+ String aTmpStr( pConfig->GetImportFormatExtension( rFormat ) );
+ if( !ImpPeekGraphicFormat( rStream, aTmpStr.ToUpperAscii(), sal_True ) )
+ return GRFILTER_FORMATERROR;
+ if ( pConfig->GetImportFormatExtension( rFormat ).EqualsIgnoreCaseAscii( "pcd" ) )
+ {
+ sal_Int32 nBase = 2; // default Base0
+ if ( pConfig->GetImportFilterType( rFormat ).EqualsIgnoreCaseAscii( "pcd_Photo_CD_Base4" ) )
+ nBase = 1;
+ else if ( pConfig->GetImportFilterType( rFormat ).EqualsIgnoreCaseAscii( "pcd_Photo_CD_Base16" ) )
+ nBase = 0;
+ String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
+ FilterConfigItem aFilterConfigItem( aFilterConfigPath );
+ aFilterConfigItem.WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), nBase );
+ }
+ }
+
+ return GRFILTER_OK;
+}
+
+//--------------------------------------------------------------------------
+
+#ifndef DISABLE_EXPORT
+
+static Graphic ImpGetScaledGraphic( const Graphic& rGraphic, FilterConfigItem& rConfigItem )
+{
+ Graphic aGraphic;
+
+ ResMgr* pResMgr = ResMgr::CreateResMgr( "svt", Application::GetSettings().GetUILanguageTag().getLocale() );
+
+ sal_Int32 nLogicalWidth = rConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "LogicalWidth" ) ), 0 );
+ sal_Int32 nLogicalHeight = rConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "LogicalHeight" ) ), 0 );
+
+ if ( rGraphic.GetType() != GRAPHIC_NONE )
+ {
+ sal_Int32 nMode = rConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ExportMode" ) ), -1 );
+
+ if ( nMode == -1 ) // the property is not there, this is possible, if the graphic filter
+ { // is called via UnoGraphicExporter and not from a graphic export Dialog
+ nMode = 0; // then we are defaulting this mode to 0
+ if ( nLogicalWidth || nLogicalHeight )
+ nMode = 2;
+ }
+
+
+ Size aOriginalSize;
+ Size aPrefSize( rGraphic.GetPrefSize() );
+ MapMode aPrefMapMode( rGraphic.GetPrefMapMode() );
+ if ( aPrefMapMode == MAP_PIXEL )
+ aOriginalSize = Application::GetDefaultDevice()->PixelToLogic( aPrefSize, MAP_100TH_MM );
+ else
+ aOriginalSize = Application::GetDefaultDevice()->LogicToLogic( aPrefSize, aPrefMapMode, MAP_100TH_MM );
+ if ( !nLogicalWidth )
+ nLogicalWidth = aOriginalSize.Width();
+ if ( !nLogicalHeight )
+ nLogicalHeight = aOriginalSize.Height();
+ if( rGraphic.GetType() == GRAPHIC_BITMAP )
+ {
+
+ // Aufloesung wird eingestellt
+ if( nMode == 1 )
+ {
+ Bitmap aBitmap( rGraphic.GetBitmap() );
+ MapMode aMap( MAP_100TH_INCH );
+
+ sal_Int32 nDPI = rConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), 75 );
+ Fraction aFrac( 1, Min( Max( nDPI, sal_Int32( 75 ) ), sal_Int32( 600 ) ) );
+
+ aMap.SetScaleX( aFrac );
+ aMap.SetScaleY( aFrac );
+
+ Size aOldSize = aBitmap.GetSizePixel();
+ aGraphic = rGraphic;
+ aGraphic.SetPrefMapMode( aMap );
+ aGraphic.SetPrefSize( Size( aOldSize.Width() * 100,
+ aOldSize.Height() * 100 ) );
+ }
+ // Groesse wird eingestellt
+ else if( nMode == 2 )
+ {
+ aGraphic = rGraphic;
+ aGraphic.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
+ aGraphic.SetPrefSize( Size( nLogicalWidth, nLogicalHeight ) );
+ }
+ else
+ aGraphic = rGraphic;
+
+ sal_Int32 nColors = rConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Color" ) ), 0 ); // #92767#
+ if ( nColors ) // graphic conversion necessary ?
+ {
+ BitmapEx aBmpEx( aGraphic.GetBitmapEx() );
+ aBmpEx.Convert( (BmpConversion)nColors ); // the entries in the xml section have the same meaning as
+ aGraphic = aBmpEx; // they have in the BmpConversion enum, so it should be
+ } // allowed to cast them
+ }
+ else
+ {
+ if( ( nMode == 1 ) || ( nMode == 2 ) )
+ {
+ GDIMetaFile aMtf( rGraphic.GetGDIMetaFile() );
+ ::com::sun::star::awt::Size aDefaultSize( 10000, 10000 );
+ Size aNewSize( OutputDevice::LogicToLogic( Size( nLogicalWidth, nLogicalHeight ), MAP_100TH_MM, aMtf.GetPrefMapMode() ) );
+
+ if( aNewSize.Width() && aNewSize.Height() )
+ {
+ const Size aPreferredSize( aMtf.GetPrefSize() );
+ aMtf.Scale( Fraction( aNewSize.Width(), aPreferredSize.Width() ),
+ Fraction( aNewSize.Height(), aPreferredSize.Height() ) );
+ }
+ aGraphic = Graphic( aMtf );
+ }
+ else
+ aGraphic = rGraphic;
+ }
+
+ }
+ else
+ aGraphic = rGraphic;
+
+ delete pResMgr;
+
+ return aGraphic;
+}
+
+#endif
+
+static String ImpCreateFullFilterPath( const String& rPath, const String& rFilterName )
+{
+ ::rtl::OUString aPathURL;
+
+ ::osl::FileBase::getFileURLFromSystemPath( rPath, aPathURL );
+ aPathURL += rtl::OUString( '/' );
+
+ ::rtl::OUString aSystemPath;
+ ::osl::FileBase::getSystemPathFromFileURL( aPathURL, aSystemPath );
+ aSystemPath += ::rtl::OUString( rFilterName );
+
+ return String( aSystemPath );
+}
+
+
+// --------------------------
+// - ImpFilterLibCacheEntry -
+// --------------------------
+
+class ImpFilterLibCache;
+
+struct ImpFilterLibCacheEntry
+{
+ ImpFilterLibCacheEntry* mpNext;
+#ifndef DISABLE_DYNLOADING
+ osl::Module maLibrary;
+#endif
+ String maFiltername;
+ PFilterCall mpfnImport;
+ PFilterDlgCall mpfnImportDlg;
+
+ ImpFilterLibCacheEntry( const String& rPathname, const String& rFiltername );
+ int operator==( const String& rFiltername ) const { return maFiltername == rFiltername; }
+
+ PFilterCall GetImportFunction();
+};
+
+// ------------------------------------------------------------------------
+
+ImpFilterLibCacheEntry::ImpFilterLibCacheEntry( const String& rPathname, const String& rFiltername ) :
+ mpNext ( NULL ),
+#ifndef DISABLE_DYNLOADING
+ maLibrary ( rPathname ),
+#endif
+ maFiltername ( rFiltername ),
+ mpfnImport ( NULL ),
+ mpfnImportDlg ( NULL )
+{
+#ifdef DISABLE_DYNLOADING
+ (void) rPathname;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+#ifdef DISABLE_DYNLOADING
+
+extern "C" sal_Bool icdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool idxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool imeGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool ipbGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool ipdGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool ipsGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool iptGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool ipxGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool iraGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool itgGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool itiGraphicImport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+
+#endif
+
+PFilterCall ImpFilterLibCacheEntry::GetImportFunction()
+{
+ if( !mpfnImport )
+ {
+#ifndef DISABLE_DYNLOADING
+ mpfnImport = (PFilterCall) maLibrary.getFunctionSymbol(rtl::OUString(IMPORT_FUNCTION_NAME));
+#else
+ if( maFiltername.EqualsAscii( "icd" ) )
+ mpfnImport = icdGraphicImport;
+ else if( maFiltername.EqualsAscii( "idx" ) )
+ mpfnImport = idxGraphicImport;
+ else if( maFiltername.EqualsAscii( "ime" ) )
+ mpfnImport = imeGraphicImport;
+ else if( maFiltername.EqualsAscii( "ipb" ) )
+ mpfnImport = ipbGraphicImport;
+ else if( maFiltername.EqualsAscii( "ipd" ) )
+ mpfnImport = ipdGraphicImport;
+ else if( maFiltername.EqualsAscii( "ips" ) )
+ mpfnImport = ipsGraphicImport;
+ else if( maFiltername.EqualsAscii( "ipt" ) )
+ mpfnImport = iptGraphicImport;
+ else if( maFiltername.EqualsAscii( "ipx" ) )
+ mpfnImport = ipxGraphicImport;
+ else if( maFiltername.EqualsAscii( "ira" ) )
+ mpfnImport = iraGraphicImport;
+ else if( maFiltername.EqualsAscii( "itg" ) )
+ mpfnImport = itgGraphicImport;
+ else if( maFiltername.EqualsAscii( "iti" ) )
+ mpfnImport = itiGraphicImport;
+#endif
+ }
+
+ return mpfnImport;
+}
+
+// ------------------------------------------------------------------------
+
+// ---------------------
+// - ImpFilterLibCache -
+// ---------------------
+
+class ImpFilterLibCache
+{
+ ImpFilterLibCacheEntry* mpFirst;
+ ImpFilterLibCacheEntry* mpLast;
+
+public:
+ ImpFilterLibCache();
+ ~ImpFilterLibCache();
+
+ ImpFilterLibCacheEntry* GetFilter( const String& rFilterPath, const String& rFiltername );
+};
+
+// ------------------------------------------------------------------------
+
+ImpFilterLibCache::ImpFilterLibCache() :
+ mpFirst ( NULL ),
+ mpLast ( NULL )
+{
+}
+
+// ------------------------------------------------------------------------
+
+ImpFilterLibCache::~ImpFilterLibCache()
+{
+ ImpFilterLibCacheEntry* pEntry = mpFirst;
+ while( pEntry )
+ {
+ ImpFilterLibCacheEntry* pNext = pEntry->mpNext;
+ delete pEntry;
+ pEntry = pNext;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+ImpFilterLibCacheEntry* ImpFilterLibCache::GetFilter( const String& rFilterPath, const String& rFilterName )
+{
+ ImpFilterLibCacheEntry* pEntry = mpFirst;
+
+ while( pEntry )
+ {
+ if( *pEntry == rFilterName )
+ break;
+ else
+ pEntry = pEntry->mpNext;
+ }
+ if( !pEntry )
+ {
+ String aPhysicalName( ImpCreateFullFilterPath( rFilterPath, rFilterName ) );
+ pEntry = new ImpFilterLibCacheEntry( aPhysicalName, rFilterName );
+#ifndef DISABLE_DYNLOADING
+ if ( pEntry->maLibrary.is() )
+#endif
+ {
+ if( !mpFirst )
+ mpFirst = mpLast = pEntry;
+ else
+ mpLast = mpLast->mpNext = pEntry;
+ }
+#ifndef DISABLE_DYNLOADING
+ else
+ {
+ delete pEntry;
+ pEntry = NULL;
+ }
+#endif
+ }
+ return pEntry;
+};
+
+// ------------------------------------------------------------------------
+
+namespace { struct Cache : public rtl::Static<ImpFilterLibCache, Cache> {}; }
+
+// -----------------
+// - GraphicFilter -
+// -----------------
+
+GraphicFilter::GraphicFilter( sal_Bool bConfig ) :
+ bUseConfig ( bConfig ),
+ nExpGraphHint ( 0 )
+{
+ ImplInit();
+}
+
+// ------------------------------------------------------------------------
+
+GraphicFilter::~GraphicFilter()
+{
+ {
+ ::osl::MutexGuard aGuard( getListMutex() );
+ for(
+ FilterList_impl::iterator it = pFilterHdlList->begin();
+ it != pFilterHdlList->end();
+ ++it
+ ) {
+ if( *it == this )
+ {
+ pFilterHdlList->erase( it );
+ break;
+ }
+ }
+ if( pFilterHdlList->empty() )
+ {
+ delete pFilterHdlList, pFilterHdlList = NULL;
+ delete pConfig;
+ }
+ }
+
+ delete pErrorEx;
+}
+
+// ------------------------------------------------------------------------
+
+void GraphicFilter::ImplInit()
+{
+ {
+ ::osl::MutexGuard aGuard( getListMutex() );
+
+ if ( !pFilterHdlList )
+ {
+ pFilterHdlList = new FilterList_impl;
+ pConfig = new FilterConfigCache( bUseConfig );
+ }
+ else
+ pConfig = pFilterHdlList->front()->pConfig;
+
+ pFilterHdlList->push_back( this );
+ }
+
+ if( bUseConfig )
+ {
+ rtl::OUString url(RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program"));
+ rtl::Bootstrap::expandMacros(url); //TODO: detect failure
+ utl::LocalFileHelper::ConvertURLToPhysicalName(url, aFilterPath);
+ }
+
+ pErrorEx = new FilterErrorEx;
+ bAbort = sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+sal_uLong GraphicFilter::ImplSetError( sal_uLong nError, const SvStream* pStm )
+{
+ pErrorEx->nFilterError = nError;
+ pErrorEx->nStreamError = pStm ? pStm->GetError() : ERRCODE_NONE;
+ return nError;
+}
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetImportFormatCount()
+{
+ return pConfig->GetImportFormatCount();
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetImportFormatNumber( const String& rFormatName )
+{
+ return pConfig->GetImportFormatNumber( rFormatName );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetImportFormatNumberForMediaType( const String& rMediaType )
+{
+ return pConfig->GetImportFormatNumberForMediaType( rMediaType );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetImportFormatNumberForShortName( const String& rShortName )
+{
+ return pConfig->GetImportFormatNumberForShortName( rShortName );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetImportFormatNumberForTypeName( const String& rType )
+{
+ return pConfig->GetImportFormatNumberForTypeName( rType );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportFormatName( sal_uInt16 nFormat )
+{
+ return pConfig->GetImportFormatName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportFormatTypeName( sal_uInt16 nFormat )
+{
+ return pConfig->GetImportFilterTypeName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportFormatMediaType( sal_uInt16 nFormat )
+{
+ return pConfig->GetImportFormatMediaType( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportFormatShortName( sal_uInt16 nFormat )
+{
+ return pConfig->GetImportFormatShortName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportOSFileType( sal_uInt16 )
+{
+ String aOSFileType;
+ return aOSFileType;
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetImportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ return pConfig->GetImportWildcard( nFormat, nEntry );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GraphicFilter::IsImportPixelFormat( sal_uInt16 nFormat )
+{
+ return pConfig->IsImportPixelFormat( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetExportFormatCount()
+{
+ return pConfig->GetExportFormatCount();
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetExportFormatNumber( const String& rFormatName )
+{
+ return pConfig->GetExportFormatNumber( rFormatName );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetExportFormatNumberForMediaType( const String& rMediaType )
+{
+ return pConfig->GetExportFormatNumberForMediaType( rMediaType );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetExportFormatNumberForShortName( const String& rShortName )
+{
+ return pConfig->GetExportFormatNumberForShortName( rShortName );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::GetExportFormatNumberForTypeName( const String& rType )
+{
+ return pConfig->GetExportFormatNumberForTypeName( rType );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportFormatName( sal_uInt16 nFormat )
+{
+ return pConfig->GetExportFormatName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportFormatTypeName( sal_uInt16 nFormat )
+{
+ return pConfig->GetExportFilterTypeName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportFormatMediaType( sal_uInt16 nFormat )
+{
+ return pConfig->GetExportFormatMediaType( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportFormatShortName( sal_uInt16 nFormat )
+{
+ return pConfig->GetExportFormatShortName( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportOSFileType( sal_uInt16 )
+{
+ String aOSFileType;
+ return aOSFileType;
+}
+
+// ------------------------------------------------------------------------
+
+String GraphicFilter::GetExportWildcard( sal_uInt16 nFormat, sal_Int32 nEntry )
+{
+ return pConfig->GetExportWildcard( nFormat, nEntry );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GraphicFilter::IsExportPixelFormat( sal_uInt16 nFormat )
+{
+ return pConfig->IsExportPixelFormat( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::CanImportGraphic( const INetURLObject& rPath,
+ sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
+{
+ sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
+ DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::CanImportGraphic() : ProtType == INET_PROT_NOT_VALID" );
+
+ String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_READ | STREAM_SHARE_DENYNONE );
+ if ( pStream )
+ {
+ nRetValue = CanImportGraphic( aMainUrl, *pStream, nFormat, pDeterminedFormat );
+ delete pStream;
+ }
+ return nRetValue;
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::CanImportGraphic( const String& rMainUrl, SvStream& rIStream,
+ sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat )
+{
+ sal_uLong nStreamPos = rIStream.Tell();
+ sal_uInt16 nRes = ImpTestOrFindFormat( rMainUrl, rIStream, nFormat );
+
+ rIStream.Seek(nStreamPos);
+
+ if( nRes==GRFILTER_OK && pDeterminedFormat!=NULL )
+ *pDeterminedFormat = nFormat;
+
+ return (sal_uInt16) ImplSetError( nRes, &rIStream );
+}
+
+// ------------------------------------------------------------------------
+//SJ: TODO, we need to create a GraphicImporter component
+sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const INetURLObject& rPath,
+ sal_uInt16 nFormat, sal_uInt16 * pDeterminedFormat, sal_uInt32 nImportFlags )
+{
+ sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
+ DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::ImportGraphic() : ProtType == INET_PROT_NOT_VALID" );
+
+ String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_READ | STREAM_SHARE_DENYNONE );
+ if ( pStream )
+ {
+ nRetValue = ImportGraphic( rGraphic, aMainUrl, *pStream, nFormat, pDeterminedFormat, nImportFlags );
+ delete pStream;
+ }
+ return nRetValue;
+}
+
+sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream,
+ sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags, WMF_EXTERNALHEADER *pExtHeader )
+{
+ return ImportGraphic( rGraphic, rPath, rIStream, nFormat, pDeterminedFormat, nImportFlags, NULL, pExtHeader );
+}
+
+//-------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::ImportGraphic( Graphic& rGraphic, const String& rPath, SvStream& rIStream,
+ sal_uInt16 nFormat, sal_uInt16* pDeterminedFormat, sal_uInt32 nImportFlags,
+ com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >* pFilterData,
+ WMF_EXTERNALHEADER *pExtHeader )
+{
+ String aFilterName;
+ sal_uLong nStmBegin;
+ sal_uInt16 nStatus;
+ GraphicReader* pContext = rGraphic.GetContext();
+ GfxLinkType eLinkType = GFX_LINK_TYPE_NONE;
+ sal_Bool bDummyContext = ( pContext == (GraphicReader*) 1 );
+ const sal_Bool bLinkSet = rGraphic.IsLink();
+ FilterConfigItem* pFilterConfigItem = NULL;
+
+ Size aPreviewSizeHint( 0, 0 );
+ sal_Bool bAllowPartialStreamRead = sal_False;
+ sal_Bool bCreateNativeLink = sal_True;
+
+ ResetLastError();
+
+ if ( pFilterData )
+ {
+ sal_Int32 i;
+ for ( i = 0; i < pFilterData->getLength(); i++ )
+ {
+ if ( (*pFilterData)[ i ].Name == "PreviewSizeHint" )
+ {
+ awt::Size aSize;
+ if ( (*pFilterData)[ i ].Value >>= aSize )
+ {
+ aPreviewSizeHint = Size( aSize.Width, aSize.Height );
+ if ( aSize.Width || aSize.Height )
+ nImportFlags |= GRFILTER_I_FLAGS_FOR_PREVIEW;
+ else
+ nImportFlags &=~GRFILTER_I_FLAGS_FOR_PREVIEW;
+ }
+ }
+ else if ( (*pFilterData)[ i ].Name == "AllowPartialStreamRead" )
+ {
+ (*pFilterData)[ i ].Value >>= bAllowPartialStreamRead;
+ if ( bAllowPartialStreamRead )
+ nImportFlags |= GRFILTER_I_FLAGS_ALLOW_PARTIAL_STREAMREAD;
+ else
+ nImportFlags &=~GRFILTER_I_FLAGS_ALLOW_PARTIAL_STREAMREAD;
+ }
+ else if ( (*pFilterData)[ i ].Name == "CreateNativeLink" )
+ {
+ (*pFilterData)[ i ].Value >>= bCreateNativeLink;
+ }
+ }
+ }
+
+ if( !pContext || bDummyContext )
+ {
+ if( bDummyContext )
+ {
+ rGraphic.SetContext( NULL );
+ nStmBegin = 0;
+ }
+ else
+ nStmBegin = rIStream.Tell();
+
+ bAbort = sal_False;
+ nStatus = ImpTestOrFindFormat( rPath, rIStream, nFormat );
+ // Falls Pending, geben wir GRFILTER_OK zurueck,
+ // um mehr Bytes anzufordern
+ if( rIStream.GetError() == ERRCODE_IO_PENDING )
+ {
+ rGraphic.SetContext( (GraphicReader*) 1 );
+ rIStream.ResetError();
+ rIStream.Seek( nStmBegin );
+ return (sal_uInt16) ImplSetError( GRFILTER_OK );
+ }
+
+ rIStream.Seek( nStmBegin );
+
+ if( ( nStatus != GRFILTER_OK ) || rIStream.GetError() )
+ return (sal_uInt16) ImplSetError( ( nStatus != GRFILTER_OK ) ? nStatus : GRFILTER_OPENERROR, &rIStream );
+
+ if( pDeterminedFormat )
+ *pDeterminedFormat = nFormat;
+
+ aFilterName = pConfig->GetImportFilterName( nFormat );
+ }
+ else
+ {
+ if( pContext && !bDummyContext )
+ aFilterName = pContext->GetUpperFilterName();
+
+ nStmBegin = 0;
+ nStatus = GRFILTER_OK;
+ }
+
+ // read graphic
+ if ( pConfig->IsImportInternalFilter( nFormat ) )
+ {
+ if( aFilterName.EqualsIgnoreCaseAscii( IMP_GIF ) )
+ {
+ if( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ if( !ImportGIF( rIStream, rGraphic ) )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ eLinkType = GFX_LINK_TYPE_NATIVE_GIF;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_PNG ) )
+ {
+ if ( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ vcl::PNGReader aPNGReader( rIStream );
+
+ // ignore animation for previews and set preview size
+ if( aPreviewSizeHint.Width() || aPreviewSizeHint.Height() )
+ {
+ // position the stream at the end of the image if requested
+ if( !bAllowPartialStreamRead )
+ aPNGReader.GetChunks();
+ }
+ else
+ {
+ // check if this PNG contains a GIF chunk!
+ const std::vector< vcl::PNGReader::ChunkData >& rChunkData = aPNGReader.GetChunks();
+ std::vector< vcl::PNGReader::ChunkData >::const_iterator aIter( rChunkData.begin() );
+ std::vector< vcl::PNGReader::ChunkData >::const_iterator aEnd ( rChunkData.end() );
+ while( aIter != aEnd )
+ {
+ // Microsoft Office is storing Animated GIFs in following chunk
+ if ( aIter->nType == PMGCHUNG_msOG )
+ {
+ sal_uInt32 nChunkSize = aIter->aData.size();
+ if ( nChunkSize > 11 )
+ {
+ const std::vector< sal_uInt8 >& rData = aIter->aData;
+ SvMemoryStream aIStrm( (void*)&rData[ 11 ], nChunkSize - 11, STREAM_READ );
+ ImportGIF( aIStrm, rGraphic );
+ eLinkType = GFX_LINK_TYPE_NATIVE_PNG;
+ break;
+ }
+ }
+ ++aIter;
+ }
+ }
+
+ if ( eLinkType == GFX_LINK_TYPE_NONE )
+ {
+ BitmapEx aBmpEx( aPNGReader.Read( aPreviewSizeHint ) );
+ if ( aBmpEx.IsEmpty() )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ {
+ rGraphic = aBmpEx;
+ eLinkType = GFX_LINK_TYPE_NATIVE_PNG;
+ }
+ }
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_JPEG ) )
+ {
+ if( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ // set LOGSIZE flag always, if not explicitly disabled
+ // (see #90508 and #106763)
+ if( 0 == ( nImportFlags & GRFILTER_I_FLAGS_DONT_SET_LOGSIZE_FOR_JPEG ) )
+ nImportFlags |= GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG;
+
+ if( !ImportJPEG( rIStream, rGraphic, NULL, nImportFlags ) )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ eLinkType = GFX_LINK_TYPE_NATIVE_JPG;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_SVG ) )
+ {
+ if( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ const sal_uInt32 nStmPos(rIStream.Tell());
+ const sal_uInt32 nStmLen(rIStream.Seek(STREAM_SEEK_TO_END) - nStmPos);
+ bool bOkay(false);
+
+ if(nStmLen)
+ {
+ SvgDataArray aNewData(new sal_uInt8[nStmLen]);
+
+ rIStream.Seek(nStmPos);
+ rIStream.Read(aNewData.get(), nStmLen);
+
+ if(!rIStream.GetError())
+ {
+ SvgDataPtr aSvgDataPtr(
+ new SvgData(
+ aNewData,
+ nStmLen,
+ rPath));
+
+ rGraphic = Graphic(aSvgDataPtr);
+ bOkay = true;
+ }
+ }
+
+ if(bOkay)
+ {
+ eLinkType = GFX_LINK_TYPE_NATIVE_SVG;
+ }
+ else
+ {
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_XBM ) )
+ {
+ if( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ if( !ImportXBM( rIStream, rGraphic ) )
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_XPM ) )
+ {
+ if( rGraphic.GetContext() == (GraphicReader*) 1 )
+ rGraphic.SetContext( NULL );
+
+ if( !ImportXPM( rIStream, rGraphic ) )
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_BMP ) ||
+ aFilterName.EqualsIgnoreCaseAscii( IMP_SVMETAFILE ) )
+ {
+ // SV interne Importfilter fuer Bitmaps und MetaFiles
+ rIStream >> rGraphic;
+ if( rIStream.GetError() )
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_WMF ) ||
+ aFilterName.EqualsIgnoreCaseAscii( IMP_EMF ) )
+ {
+ GDIMetaFile aMtf;
+ if( !ConvertWMFToGDIMetaFile( rIStream, aMtf, NULL, pExtHeader ) )
+ nStatus = GRFILTER_FORMATERROR;
+ else
+ {
+ rGraphic = aMtf;
+ eLinkType = GFX_LINK_TYPE_NATIVE_WMF;
+ }
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( IMP_SVSGF )
+ || aFilterName.EqualsIgnoreCaseAscii( IMP_SVSGV ) )
+ {
+ sal_uInt16 nVersion;
+ unsigned char nTyp = CheckSgfTyp( rIStream, nVersion );
+
+ switch( nTyp )
+ {
+ case SGF_BITIMAGE:
+ {
+ SvMemoryStream aTempStream;
+ if( aTempStream.GetError() )
+ return GRFILTER_OPENERROR;
+
+ if( !SgfBMapFilter( rIStream, aTempStream ) )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ {
+ aTempStream.Seek( 0L );
+ aTempStream >> rGraphic;
+
+ if( aTempStream.GetError() )
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ }
+ break;
+
+ case SGF_SIMPVECT:
+ {
+ GDIMetaFile aMtf;
+ if( !SgfVectFilter( rIStream, aMtf ) )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ rGraphic = Graphic( aMtf );
+ }
+ break;
+
+ case SGF_STARDRAW:
+ {
+ if( nVersion != SGV_VERSION )
+ nStatus = GRFILTER_VERSIONERROR;
+ else
+ {
+ GDIMetaFile aMtf;
+ if( !SgfSDrwFilter( rIStream, aMtf,
+ INetURLObject(aFilterPath) ) )
+ {
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ else
+ rGraphic = Graphic( aMtf );
+ }
+ }
+ break;
+
+ default:
+ {
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ break;
+ }
+ }
+ else
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ else
+ {
+ ImpFilterLibCacheEntry* pFilter = NULL;
+
+ // find first filter in filter paths
+ sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
+ ImpFilterLibCache &rCache = Cache::get();
+ for( i = 0; ( i < nTokenCount ) && ( pFilter == NULL ); i++ )
+ pFilter = rCache.GetFilter( getToken(aFilterPath, i, ';'), aFilterName );
+ if( !pFilter )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ {
+ PFilterCall pFunc = pFilter->GetImportFunction();
+
+ if( !pFunc )
+ nStatus = GRFILTER_FILTERERROR;
+ else
+ {
+ String aShortName;
+ if( nFormat != GRFILTER_FORMAT_DONTKNOW )
+ {
+ aShortName = GetImportFormatShortName( nFormat ).ToUpperAscii();
+ if ( ( pFilterConfigItem == NULL ) && aShortName.EqualsAscii( "PCD" ) )
+ {
+ String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
+ pFilterConfigItem = new FilterConfigItem( aFilterConfigPath );
+ }
+ }
+ if( !(*pFunc)( rIStream, rGraphic, pFilterConfigItem, sal_False ) )
+ nStatus = GRFILTER_FORMATERROR;
+ else
+ {
+ // try to set link type if format matches
+ if( nFormat != GRFILTER_FORMAT_DONTKNOW )
+ {
+ if( aShortName.CompareToAscii( TIF_SHORTNAME ) == COMPARE_EQUAL )
+ eLinkType = GFX_LINK_TYPE_NATIVE_TIF;
+ else if( aShortName.CompareToAscii( MET_SHORTNAME ) == COMPARE_EQUAL )
+ eLinkType = GFX_LINK_TYPE_NATIVE_MET;
+ else if( aShortName.CompareToAscii( PCT_SHORTNAME ) == COMPARE_EQUAL )
+ eLinkType = GFX_LINK_TYPE_NATIVE_PCT;
+ }
+ }
+ }
+ }
+ }
+
+ if( nStatus == GRFILTER_OK && bCreateNativeLink && ( eLinkType != GFX_LINK_TYPE_NONE ) && !rGraphic.GetContext() && !bLinkSet )
+ {
+ const sal_uLong nStmEnd = rIStream.Tell();
+ const sal_uLong nBufSize = nStmEnd - nStmBegin;
+
+ if( nBufSize )
+ {
+ sal_uInt8* pBuf=0;
+ try
+ {
+ pBuf = new sal_uInt8[ nBufSize ];
+ }
+ catch (const std::bad_alloc&)
+ {
+ nStatus = GRFILTER_TOOBIG;
+ }
+
+ if( nStatus == GRFILTER_OK )
+ {
+ rIStream.Seek( nStmBegin );
+ rIStream.Read( pBuf, nBufSize );
+ rGraphic.SetLink( GfxLink( pBuf, nBufSize, eLinkType, sal_True ) );
+ }
+ }
+ }
+
+ // Set error code or try to set native buffer
+ if( nStatus != GRFILTER_OK )
+ {
+ if( bAbort )
+ nStatus = GRFILTER_ABORT;
+
+ ImplSetError( nStatus, &rIStream );
+ rIStream.Seek( nStmBegin );
+ rGraphic.Clear();
+ }
+
+ delete pFilterConfigItem;
+ return nStatus;
+}
+
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const INetURLObject& rPath,
+ sal_uInt16 nFormat, const uno::Sequence< beans::PropertyValue >* pFilterData )
+{
+#ifdef DISABLE_EXPORT
+ (void) rGraphic;
+ (void) rPath;
+ (void) nFormat;
+ (void) pFilterData;
+
+ return GRFILTER_FORMATERROR;
+#else
+ RTL_LOGFILE_CONTEXT( aLog, "GraphicFilter::ExportGraphic() (thb)" );
+ sal_uInt16 nRetValue = GRFILTER_FORMATERROR;
+ DBG_ASSERT( rPath.GetProtocol() != INET_PROT_NOT_VALID, "GraphicFilter::ExportGraphic() : ProtType == INET_PROT_NOT_VALID" );
+ sal_Bool bAlreadyExists = ImplDirEntryHelper::Exists( rPath );
+
+ String aMainUrl( rPath.GetMainURL( INetURLObject::NO_DECODE ) );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aMainUrl, STREAM_WRITE | STREAM_TRUNC );
+ if ( pStream )
+ {
+ nRetValue = ExportGraphic( rGraphic, aMainUrl, *pStream, nFormat, pFilterData );
+ delete pStream;
+
+ if( ( GRFILTER_OK != nRetValue ) && !bAlreadyExists )
+ ImplDirEntryHelper::Kill( aMainUrl );
+ }
+ return nRetValue;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+#ifdef DISABLE_DYNLOADING
+
+#ifndef DISABLE_EXPORT
+
+extern "C" sal_Bool egiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool emeGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool epbGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool epgGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool eppGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool epsGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool eptGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool eraGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool etiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+extern "C" sal_Bool expGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pConfigItem, sal_Bool );
+
+#endif
+
+#endif
+
+sal_uInt16 GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& rPath,
+ SvStream& rOStm, sal_uInt16 nFormat, const uno::Sequence< beans::PropertyValue >* pFilterData )
+{
+#ifdef DISABLE_EXPORT
+ (void) rGraphic;
+ (void) rPath;
+ (void) rOStm;
+ (void) nFormat;
+ (void) pFilterData;
+
+ return GRFILTER_FORMATERROR;
+#else
+ RTL_LOGFILE_CONTEXT( aLog, "GraphicFilter::ExportGraphic() (thb)" );
+ sal_uInt16 nFormatCount = GetExportFormatCount();
+
+ ResetLastError();
+ nExpGraphHint = 0;
+
+ if( nFormat == GRFILTER_FORMAT_DONTKNOW )
+ {
+ INetURLObject aURL( rPath );
+ String aExt( aURL.GetFileExtension().toAsciiUpperCase() );
+
+
+ for( sal_uInt16 i = 0; i < nFormatCount; i++ )
+ {
+ if ( pConfig->GetExportFormatExtension( i ).EqualsIgnoreCaseAscii( aExt ) )
+ {
+ nFormat=i;
+ break;
+ }
+ }
+ }
+ if( nFormat >= nFormatCount )
+ return (sal_uInt16) ImplSetError( GRFILTER_FORMATERROR );
+
+ FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
+ String aFilterName( pConfig->GetExportFilterName( nFormat ) );
+
+ bAbort = sal_False;
+ sal_uInt16 nStatus = GRFILTER_OK;
+ GraphicType eType;
+ Graphic aGraphic( rGraphic );
+
+ aGraphic = ImpGetScaledGraphic( rGraphic, aConfigItem );
+ eType = aGraphic.GetType();
+
+ if( pConfig->IsExportPixelFormat( nFormat ) )
+ {
+ if( eType != GRAPHIC_BITMAP )
+ {
+ Size aSizePixel;
+ sal_uLong nColorCount,nBitsPerPixel,nNeededMem,nMaxMem;
+ VirtualDevice aVirDev;
+
+ // Maximalen Speicherbedarf fuer das Bildes holen:
+// if( GetOptionsConfig() )
+// nMaxMem = (UINT32)GetOptionsConfig()->ReadKey( "VEC-TO-PIX-MAX-KB", "1024" ).ToInt32();
+// else
+ nMaxMem = 1024;
+
+ nMaxMem *= 1024; // In Bytes
+
+ // Berechnen, wie gross das Bild normalerweise werden wuerde:
+ aSizePixel=aVirDev.LogicToPixel(aGraphic.GetPrefSize(),aGraphic.GetPrefMapMode());
+
+ // Berechnen, wieviel Speicher das Bild benoetigen wuerde:
+ nColorCount=aVirDev.GetColorCount();
+ if (nColorCount<=2) nBitsPerPixel=1;
+ else if (nColorCount<=4) nBitsPerPixel=2;
+ else if (nColorCount<=16) nBitsPerPixel=4;
+ else if (nColorCount<=256) nBitsPerPixel=8;
+ else if (nColorCount<=65536) nBitsPerPixel=16;
+ else nBitsPerPixel=24;
+ nNeededMem=((sal_uLong)aSizePixel.Width()*(sal_uLong)aSizePixel.Height()*nBitsPerPixel+7)/8;
+
+ // ggf. Groesse des Bildes einschraenken:
+ if (nMaxMem<nNeededMem)
+ {
+ double fFak=sqrt(((double)nMaxMem)/((double)nNeededMem));
+ aSizePixel.Width()=(sal_uLong)(((double)aSizePixel.Width())*fFak);
+ aSizePixel.Height()=(sal_uLong)(((double)aSizePixel.Height())*fFak);
+ }
+
+ aVirDev.SetMapMode(MapMode(MAP_PIXEL));
+ aVirDev.SetOutputSizePixel(aSizePixel);
+ Graphic aGraphic2=aGraphic;
+ aGraphic2.Draw(&aVirDev,Point(0,0),aSizePixel); // Gemein: dies aendert den MapMode
+ aVirDev.SetMapMode(MapMode(MAP_PIXEL));
+ aGraphic=Graphic(aVirDev.GetBitmap(Point(0,0),aSizePixel));
+ }
+ }
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ if( GRFILTER_OK == nStatus )
+ {
+ if ( pConfig->IsExportInternalFilter( nFormat ) )
+ {
+ if( aFilterName.EqualsIgnoreCaseAscii( EXP_BMP ) )
+ {
+ Bitmap aBmp( aGraphic.GetBitmap() );
+ sal_Int32 nColorRes = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Colors" ) ), 0 );
+ if ( nColorRes && ( nColorRes <= (sal_uInt16)BMP_CONVERSION_24BIT) )
+ {
+ if( !aBmp.Convert( (BmpConversion) nColorRes ) )
+ aBmp = aGraphic.GetBitmap();
+ }
+ ResMgr* pResMgr = CREATERESMGR( svt );
+ sal_Bool bRleCoding = aConfigItem.ReadBool( String( RTL_CONSTASCII_USTRINGPARAM( "RLE_Coding" ) ), sal_True );
+ // Wollen wir RLE-Kodiert speichern?
+ aBmp.Write( rOStm, bRleCoding );
+ delete pResMgr;
+
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( EXP_SVMETAFILE ) )
+ {
+ sal_Int32 nVersion = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ), 0 ) ;
+ if ( nVersion )
+ rOStm.SetVersion( nVersion );
+ GDIMetaFile aMTF;
+
+ if ( eType != GRAPHIC_BITMAP )
+ aMTF = aGraphic.GetGDIMetaFile();
+ else
+ {
+ VirtualDevice aVirDev;
+
+ aMTF.Record( &aVirDev );
+ aGraphic.Draw( &aVirDev, Point(), aGraphic.GetPrefSize() );
+ aMTF.Stop();
+ aMTF.SetPrefSize( aGraphic.GetPrefSize() );
+ aMTF.SetPrefMapMode( aGraphic.GetPrefMapMode() );
+ }
+ aMTF.Write( rOStm );
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_WMF ) )
+ {
+ if( eType == GRAPHIC_GDIMETAFILE )
+ {
+ if ( !ConvertGDIMetaFileToWMF( aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem ) )
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ else
+ {
+ Bitmap aBmp( aGraphic.GetBitmap() );
+ GDIMetaFile aMTF;
+ VirtualDevice aVirDev;
+
+ aMTF.Record( &aVirDev );
+ aVirDev.DrawBitmap( Point(), aBmp );
+ aMTF.Stop();
+ aMTF.SetPrefSize( aBmp.GetSizePixel() );
+
+ if( !ConvertGDIMetaFileToWMF( aMTF, rOStm, &aConfigItem ) )
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_EMF ) )
+ {
+ if( eType == GRAPHIC_GDIMETAFILE )
+ {
+ if ( !ConvertGDIMetaFileToEMF( aGraphic.GetGDIMetaFile(), rOStm, &aConfigItem ) )
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ else
+ {
+ Bitmap aBmp( aGraphic.GetBitmap() );
+ GDIMetaFile aMTF;
+ VirtualDevice aVirDev;
+
+ aMTF.Record( &aVirDev );
+ aVirDev.DrawBitmap( Point(), aBmp );
+ aMTF.Stop();
+ aMTF.SetPrefSize( aBmp.GetSizePixel() );
+
+ if( !ConvertGDIMetaFileToEMF( aMTF, rOStm, &aConfigItem ) )
+ nStatus = GRFILTER_FORMATERROR;
+ }
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( EXP_JPEG ) )
+ {
+ bool bExportedGrayJPEG = false;
+ if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) )
+ nStatus = GRFILTER_FORMATERROR;
+ nExpGraphHint = bExportedGrayJPEG ? GRFILTER_OUTHINT_GREY : 0;
+
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if ( aFilterName.EqualsIgnoreCaseAscii( EXP_PNG ) )
+ {
+ vcl::PNGWriter aPNGWriter( aGraphic.GetBitmapEx(), pFilterData );
+ if ( pFilterData )
+ {
+ sal_Int32 k, j, i = 0;
+ for ( i = 0; i < pFilterData->getLength(); i++ )
+ {
+ if ( (*pFilterData)[ i ].Name == "AdditionalChunks" )
+ {
+ com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aAdditionalChunkSequence;
+ if ( (*pFilterData)[ i ].Value >>= aAdditionalChunkSequence )
+ {
+ for ( j = 0; j < aAdditionalChunkSequence.getLength(); j++ )
+ {
+ if ( aAdditionalChunkSequence[ j ].Name.getLength() == 4 )
+ {
+ sal_uInt32 nChunkType = 0;
+ for ( k = 0; k < 4; k++ )
+ {
+ nChunkType <<= 8;
+ nChunkType |= (sal_uInt8)aAdditionalChunkSequence[ j ].Name[ k ];
+ }
+ com::sun::star::uno::Sequence< sal_Int8 > aByteSeq;
+ if ( aAdditionalChunkSequence[ j ].Value >>= aByteSeq )
+ {
+ std::vector< vcl::PNGWriter::ChunkData >& rChunkData = aPNGWriter.GetChunks();
+ if ( !rChunkData.empty() )
+ {
+ sal_uInt32 nChunkLen = aByteSeq.getLength();
+
+ vcl::PNGWriter::ChunkData aChunkData;
+ aChunkData.nType = nChunkType;
+ if ( nChunkLen )
+ {
+ aChunkData.aData.resize( nChunkLen );
+ memcpy( &aChunkData.aData[ 0 ], aByteSeq.getConstArray(), nChunkLen );
+ }
+ std::vector< vcl::PNGWriter::ChunkData >::iterator aIter = rChunkData.end() - 1;
+ rChunkData.insert( aIter, aChunkData );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ aPNGWriter.Write( rOStm );
+
+ if( rOStm.GetError() )
+ nStatus = GRFILTER_IOERROR;
+ }
+ else if( aFilterName.EqualsIgnoreCaseAscii( EXP_SVG ) )
+ {
+ bool bDone(false);
+
+ // do we have a native SVG RenderGraphic, whose data can be written directly?
+ const SvgDataPtr aSvgDataPtr(rGraphic.getSvgData());
+
+ if(aSvgDataPtr.get() && aSvgDataPtr->getSvgDataArrayLength())
+ {
+ rOStm.Write(aSvgDataPtr->getSvgDataArray().get(), aSvgDataPtr->getSvgDataArrayLength());
+
+ if( rOStm.GetError() )
+ {
+ nStatus = GRFILTER_IOERROR;
+ }
+ else
+ {
+ bDone = true;
+ }
+ }
+
+ if( !bDone )
+ {
+ // do the normal GDIMetaFile export instead
+ try
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+
+ if( xMgr.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > xSaxWriter(
+ xml::sax::Writer::create( xContext ), uno::UNO_QUERY_THROW);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::svg::XSVGWriter > xSVGWriter( xMgr->createInstance(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svg.SVGWriter" )) ), ::com::sun::star::uno::UNO_QUERY );
+
+ if( xSaxWriter.is() && xSVGWriter.is() )
+ {
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XActiveDataSource > xActiveDataSource(
+ xSaxWriter, ::com::sun::star::uno::UNO_QUERY );
+
+ if( xActiveDataSource.is() )
+ {
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xStmIf(
+ static_cast< ::cppu::OWeakObject* >( new ImpFilterOutputStream( rOStm ) ) );
+
+ SvMemoryStream aMemStm( 65535, 65535 );
+
+ ( (GDIMetaFile&) aGraphic.GetGDIMetaFile() ).Write( aMemStm );
+
+ xActiveDataSource->setOutputStream( ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >(
+ xStmIf, ::com::sun::star::uno::UNO_QUERY ) );
+ ::com::sun::star::uno::Sequence< sal_Int8 > aMtfSeq( (sal_Int8*) aMemStm.GetData(), aMemStm.Tell() );
+ xSVGWriter->write( xSaxWriter, aMtfSeq );
+ }
+ }
+ }
+ }
+ catch(const ::com::sun::star::uno::Exception&)
+ {
+ nStatus = GRFILTER_IOERROR;
+ }
+ }
+ }
+ else
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ else
+ {
+ sal_Int32 i, nTokenCount = getTokenCount(aFilterPath, ';');
+ for ( i = 0; i < nTokenCount; i++ )
+ {
+#ifndef DISABLE_DYNLOADING
+ String aPhysicalName( ImpCreateFullFilterPath( getToken(aFilterPath, i, ';'), aFilterName ) );
+ osl::Module aLibrary( aPhysicalName );
+
+ PFilterCall pFunc = (PFilterCall) aLibrary.getFunctionSymbol(rtl::OUString(EXPORT_FUNCTION_NAME));
+ // Dialog in DLL ausfuehren
+#else
+ PFilterCall pFunc = NULL;
+ if( aFilterName.EqualsAscii( "egi" ) )
+ pFunc = egiGraphicExport;
+ else if( aFilterName.EqualsAscii( "eme" ) )
+ pFunc = emeGraphicExport;
+ else if( aFilterName.EqualsAscii( "epb" ) )
+ pFunc = epbGraphicExport;
+ else if( aFilterName.EqualsAscii( "epg" ) )
+ pFunc = epgGraphicExport;
+ else if( aFilterName.EqualsAscii( "epp" ) )
+ pFunc = eppGraphicExport;
+ else if( aFilterName.EqualsAscii( "eps" ) )
+ pFunc = epsGraphicExport;
+ else if( aFilterName.EqualsAscii( "ept" ) )
+ pFunc = eptGraphicExport;
+ else if( aFilterName.EqualsAscii( "era" ) )
+ pFunc = eraGraphicExport;
+ else if( aFilterName.EqualsAscii( "eti" ) )
+ pFunc = etiGraphicExport;
+ else if( aFilterName.EqualsAscii( "exp" ) )
+ pFunc = expGraphicExport;
+#endif
+ if( pFunc )
+ {
+ if ( !(*pFunc)( rOStm, aGraphic, &aConfigItem, sal_False ) )
+ nStatus = GRFILTER_FORMATERROR;
+ break;
+ }
+ else
+ nStatus = GRFILTER_FILTERERROR;
+ }
+ }
+ }
+ if( nStatus != GRFILTER_OK )
+ {
+ if( bAbort )
+ nStatus = GRFILTER_ABORT;
+
+ ImplSetError( nStatus, &rOStm );
+ }
+ return nStatus;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GraphicFilter::Setup( sal_uInt16 )
+{
+ return sal_False;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GraphicFilter::HasExportDialog( sal_uInt16 nFormat )
+{
+ return pConfig->IsExportDialog( nFormat );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GraphicFilter::DoExportDialog( Window* pWindow, sal_uInt16 nFormat )
+{
+ return DoExportDialog( pWindow, nFormat, FUNIT_MM );
+}
+
+sal_Bool GraphicFilter::DoExportDialog( Window*, sal_uInt16 nFormat, FieldUnit )
+{
+#ifdef DISABLE_EXPORT
+ (void) nFormat;
+
+ return sal_False;
+#else
+ sal_Bool bRet = sal_False;
+ com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >
+ xSMgr( ::comphelper::getProcessServiceFactory() );
+
+ uno::Reference< com::sun::star::uno::XInterface > xFilterOptionsDialog
+ ( xSMgr->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.svtools.SvFilterOptionsDialog" )) ),
+ com::sun::star::uno::UNO_QUERY );
+ if ( xFilterOptionsDialog.is() )
+ {
+ com::sun::star::uno::Reference< com::sun::star::ui::dialogs::XExecutableDialog > xExecutableDialog
+ ( xFilterOptionsDialog, ::com::sun::star::uno::UNO_QUERY );
+ com::sun::star::uno::Reference< com::sun::star::beans::XPropertyAccess > xPropertyAccess
+ ( xFilterOptionsDialog, ::com::sun::star::uno::UNO_QUERY );
+ if ( xExecutableDialog.is() && xPropertyAccess.is() )
+ {
+ com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aMediaDescriptor( 1 );
+ aMediaDescriptor[ 0 ].Name = String( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
+ rtl::OUString aStr( pConfig->GetExportInternalFilterName( nFormat ) );
+ aMediaDescriptor[ 0 ].Value <<= aStr;
+ xPropertyAccess->setPropertyValues( aMediaDescriptor );
+ bRet = xExecutableDialog->execute() == com::sun::star::ui::dialogs::ExecutableDialogResults::OK;
+ }
+ }
+ return bRet;
+#endif
+}
+
+// ------------------------------------------------------------------------
+
+const FilterErrorEx& GraphicFilter::GetLastError() const
+{
+ return *pErrorEx;
+}
+
+// ------------------------------------------------------------------------
+
+void GraphicFilter::ResetLastError()
+{
+ pErrorEx->nFilterError = pErrorEx->nStreamError = 0UL;
+}
+
+// ------------------------------------------------------------------------
+
+const Link GraphicFilter::GetFilterCallback() const
+{
+ const Link aLink( LINK( this, GraphicFilter, FilterCallback ) );
+ return aLink;
+}
+
+// ------------------------------------------------------------------------
+
+IMPL_LINK( GraphicFilter, FilterCallback, ConvertData*, pData )
+{
+ long nRet = 0L;
+
+ if( pData )
+ {
+ sal_uInt16 nFormat = GRFILTER_FORMAT_DONTKNOW;
+ rtl::OString aShortName;
+ switch( pData->mnFormat )
+ {
+ case( CVT_BMP ): aShortName = BMP_SHORTNAME; break;
+ case( CVT_GIF ): aShortName = GIF_SHORTNAME; break;
+ case( CVT_JPG ): aShortName = JPG_SHORTNAME; break;
+ case( CVT_MET ): aShortName = MET_SHORTNAME; break;
+ case( CVT_PCT ): aShortName = PCT_SHORTNAME; break;
+ case( CVT_PNG ): aShortName = PNG_SHORTNAME; break;
+ case( CVT_SVM ): aShortName = SVM_SHORTNAME; break;
+ case( CVT_TIF ): aShortName = TIF_SHORTNAME; break;
+ case( CVT_WMF ): aShortName = WMF_SHORTNAME; break;
+ case( CVT_EMF ): aShortName = EMF_SHORTNAME; break;
+ case( CVT_SVG ): aShortName = SVG_SHORTNAME; break;
+
+ default:
+ break;
+ }
+ if( GRAPHIC_NONE == pData->maGraphic.GetType() || pData->maGraphic.GetContext() ) // Import
+ {
+ // Import
+ nFormat = GetImportFormatNumberForShortName( rtl::OStringToOUString( aShortName, RTL_TEXTENCODING_UTF8) );
+ nRet = ImportGraphic( pData->maGraphic, String(), pData->mrStm, nFormat ) == 0;
+ }
+#ifndef DISABLE_EXPORT
+ else if( !aShortName.isEmpty() )
+ {
+ // Export
+ nFormat = GetExportFormatNumberForShortName( rtl::OStringToOUString(aShortName, RTL_TEXTENCODING_UTF8) );
+ nRet = ExportGraphic( pData->maGraphic, String(), pData->mrStm, nFormat ) == 0;
+ }
+#endif
+ }
+ return nRet;
+}
+
+namespace
+{
+ class StandardGraphicFilter
+ {
+ public:
+ StandardGraphicFilter()
+ {
+ m_aFilter.GetImportFormatCount();
+ }
+ GraphicFilter m_aFilter;
+ };
+
+ class theGraphicFilter : public rtl::Static<StandardGraphicFilter, theGraphicFilter> {};
+}
+
+GraphicFilter& GraphicFilter::GetGraphicFilter()
+{
+ return theGraphicFilter::get().m_aFilter;
+}
+
+int GraphicFilter::LoadGraphic( const String &rPath, const String &rFilterName,
+ Graphic& rGraphic, GraphicFilter* pFilter,
+ sal_uInt16* pDeterminedFormat )
+{
+ if ( !pFilter )
+ pFilter = &GetGraphicFilter();
+
+ const sal_uInt16 nFilter = rFilterName.Len() && pFilter->GetImportFormatCount()
+ ? pFilter->GetImportFormatNumber( rFilterName )
+ : GRFILTER_FORMAT_DONTKNOW;
+
+ SvStream* pStream = NULL;
+ INetURLObject aURL( rPath );
+
+ if ( aURL.HasError() || INET_PROT_NOT_VALID == aURL.GetProtocol() )
+ {
+ aURL.SetSmartProtocol( INET_PROT_FILE );
+ aURL.SetSmartURL( rPath );
+ }
+ else if ( INET_PROT_FILE != aURL.GetProtocol() )
+ {
+ pStream = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ );
+ }
+
+ int nRes = GRFILTER_OK;
+ if ( !pStream )
+ nRes = pFilter->ImportGraphic( rGraphic, aURL, nFilter, pDeterminedFormat );
+ else
+ nRes = pFilter->ImportGraphic( rGraphic, rPath, *pStream, nFilter, pDeterminedFormat );
+
+#ifdef DBG_UTIL
+ if( nRes )
+ DBG_WARNING2( "GrafikFehler [%d] - [%s]", nRes, rPath.GetBuffer() );
+#endif
+
+ return nRes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
new file mode 100644
index 000000000000..3cf7abfef5a1
--- /dev/null
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -0,0 +1,1135 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <string.h>
+#include <stdio.h>
+#include <tools/stream.hxx>
+#include <vcl/outdev.hxx>
+#include <svtools/filter.hxx>
+#include "FilterConfigCache.hxx"
+#include <unotools/ucbstreamhelper.hxx>
+
+#define DATA_SIZE 640
+
+sal_uInt8* ImplSearchEntry( sal_uInt8* , sal_uInt8* , sal_uLong , sal_uLong );
+
+GraphicDescriptor::GraphicDescriptor( const INetURLObject& rPath ) :
+ pFileStm( ::utl::UcbStreamHelper::CreateStream( rPath.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ ) ),
+ aPathExt( rPath.GetFileExtension().toAsciiLowerCase() ),
+ bOwnStream( sal_True )
+{
+ ImpConstruct();
+}
+
+GraphicDescriptor::GraphicDescriptor( SvStream& rInStream, const String* pPath) :
+ pFileStm ( &rInStream ),
+ bOwnStream ( sal_False )
+{
+ ImpConstruct();
+
+ if ( pPath )
+ {
+ INetURLObject aURL( *pPath );
+ aPathExt = aURL.GetFileExtension().toAsciiLowerCase();
+ }
+}
+
+GraphicDescriptor::~GraphicDescriptor()
+{
+ if ( bOwnStream )
+ delete pFileStm;
+}
+
+sal_Bool GraphicDescriptor::Detect( sal_Bool bExtendedInfo )
+{
+ sal_Bool bRet = sal_False;
+ if ( pFileStm && !pFileStm->GetError() )
+ {
+ SvStream& rStm = *pFileStm;
+ sal_uInt16 nOldFormat = rStm.GetNumberFormatInt();
+
+ if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPCX( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectDXF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectMET( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectSGF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectSGV( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectSVM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectWMF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectEMF( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectSVG( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPCT( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectXBM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectXPM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPBM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPGM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPPM( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectRAS( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectTGA( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPSD( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectEPS( rStm, bExtendedInfo ) ) bRet = sal_True;
+ else if ( ImpDetectPCD( rStm, bExtendedInfo ) ) bRet = sal_True;
+
+ rStm.SetNumberFormatInt( nOldFormat );
+ }
+ return bRet;
+}
+
+void GraphicDescriptor::ImpConstruct()
+{
+ nFormat = GFF_NOT;
+ nBitsPerPixel = 0;
+ nPlanes = 0;
+ bCompressed = sal_False;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_uInt16 nTemp16;
+ sal_Bool bRet = sal_False;
+ sal_Int32 nStmPos = rStm.Tell();
+
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStm >> nTemp16;
+
+ // OS/2-BitmapArray
+ if ( nTemp16 == 0x4142 )
+ {
+ rStm.SeekRel( 0x0c );
+ rStm >> nTemp16;
+ }
+
+ // Bitmap
+ if ( nTemp16 == 0x4d42 )
+ {
+ nFormat = GFF_BMP;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uInt32 nTemp32;
+ sal_uInt32 nCompression;
+
+ // bis zur ersten Information
+ rStm.SeekRel( 0x10 );
+
+ // PixelBreite auslesen
+ rStm >> nTemp32;
+ aPixSize.Width() = nTemp32;
+
+ // PixelHoehe auslesen
+ rStm >> nTemp32;
+ aPixSize.Height() = nTemp32;
+
+ // Planes auslesen
+ rStm >> nTemp16;
+ nPlanes = nTemp16;
+
+ // BitCount auslesen
+ rStm >> nTemp16;
+ nBitsPerPixel = nTemp16;
+
+ // Compression auslesen
+ rStm >> nTemp32;
+ bCompressed = ( ( nCompression = nTemp32 ) > 0 );
+
+ // logische Breite
+ rStm.SeekRel( 4 );
+ rStm >> nTemp32;
+ if ( nTemp32 )
+ aLogSize.Width() = ( aPixSize.Width() * 100000 ) / nTemp32;
+
+ // logische Hoehe
+ rStm >> nTemp32;
+ if ( nTemp32 )
+ aLogSize.Height() = ( aPixSize.Height() * 100000 ) / nTemp32;
+
+ // Wir wollen noch etwas feiner differenzieren und
+ // auf sinnvolle Werte ueberpruefen ( Bug-Id #29001 )
+ if ( ( nBitsPerPixel > 24 ) || ( nCompression > 3 ) )
+ {
+ nFormat = GFF_NOT;
+ bRet = sal_False;
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectGIF( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_uInt32 n32;
+ sal_uInt16 n16;
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cByte;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStm >> n32;
+
+ if ( n32 == 0x38464947 )
+ {
+ rStm >> n16;
+ if ( ( n16 == 0x6137 ) || ( n16 == 0x6139 ) )
+ {
+ nFormat = GFF_GIF;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uInt16 nTemp16;
+
+ // PixelBreite auslesen
+ rStm >> nTemp16;
+ aPixSize.Width() = nTemp16;
+
+ // PixelHoehe auslesen
+ rStm >> nTemp16;
+ aPixSize.Height() = nTemp16;
+
+ // Bits/Pixel auslesen
+ rStm >> cByte;
+ nBitsPerPixel = ( ( cByte & 112 ) >> 4 ) + 1;
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+// returns the next jpeg marker, a return value of 0 represents an error
+sal_uInt8 ImpDetectJPG_GetNextMarker( SvStream& rStm )
+{
+ sal_uInt8 nByte;
+ do
+ {
+ do
+ {
+ rStm >> nByte;
+ if ( rStm.IsEof() || rStm.GetError() ) // as 0 is not allowed as marker,
+ return 0; // we can use it as errorcode
+ }
+ while ( nByte != 0xff );
+ do
+ {
+ rStm >> nByte;
+ if ( rStm.IsEof() || rStm.GetError() )
+ return 0;
+ }
+ while( nByte == 0xff );
+ }
+ while( nByte == 0 ); // 0xff00 represents 0xff and not a marker,
+ // the marker detection has to be restartet.
+ return nByte;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_uInt32 nTemp32;
+ sal_Bool bRet = sal_False;
+
+ sal_Int32 nStmPos = rStm.Tell();
+
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStm >> nTemp32;
+
+ // compare upper 24 bits
+ if( 0xffd8ff00 == ( nTemp32 & 0xffffff00 ) )
+ {
+ nFormat = GFF_JPG;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ rStm.SeekRel( -2 );
+
+ sal_uInt32 nError( rStm.GetError() );
+
+ sal_Bool bScanFailure = sal_False;
+ sal_Bool bScanFinished = sal_False;
+
+ while( !bScanFailure && !bScanFinished && !rStm.IsEof() && !rStm.GetError() )
+ {
+ sal_uInt8 nMarker = ImpDetectJPG_GetNextMarker( rStm );
+ switch( nMarker )
+ {
+ // fixed size marker, not having a two byte length parameter
+ case 0xd0 : // RST0
+ case 0xd1 :
+ case 0xd2 :
+ case 0xd3 :
+ case 0xd4 :
+ case 0xd5 :
+ case 0xd6 :
+ case 0xd7 : // RST7
+ case 0x01 : // TEM
+ break;
+
+ case 0xd8 : // SOI (has already been checked, there should not be a second one)
+ case 0x00 : // marker is invalid, we should stop now
+ bScanFailure = sal_True;
+ break;
+
+ case 0xd9 : // EOI
+ bScanFinished = sal_True;
+ break;
+
+ // per default we assume marker segments conaining a length parameter
+ default :
+ {
+ sal_uInt16 nLength;
+ rStm >> nLength;
+
+ if ( nLength < 2 )
+ bScanFailure = sal_True;
+ else
+ {
+ sal_uInt32 nNextMarkerPos = rStm.Tell() + nLength - 2;
+ switch( nMarker )
+ {
+ case 0xe0 : // APP0 Marker
+ {
+ if ( nLength == 16 )
+ {
+ sal_Int32 nIdentifier;
+ rStm >> nIdentifier;
+ if ( nIdentifier == 0x4a464946 ) // JFIF Identifier
+ {
+ sal_uInt8 nStringTerminator;
+ sal_uInt8 nMajorRevision;
+ sal_uInt8 nMinorRevision;
+ sal_uInt8 nUnits;
+ sal_uInt16 nHorizontalResolution;
+ sal_uInt16 nVerticalResolution;
+ sal_uInt8 nHorzThumbnailPixelCount;
+ sal_uInt8 nVertThumbnailPixelCount;
+
+ rStm >> nStringTerminator
+ >> nMajorRevision
+ >> nMinorRevision
+ >> nUnits
+ >> nHorizontalResolution
+ >> nVerticalResolution
+ >> nHorzThumbnailPixelCount
+ >> nVertThumbnailPixelCount;
+
+ // setting the logical size
+ if ( nUnits && nHorizontalResolution && nVerticalResolution )
+ {
+ MapMode aMap;
+ aMap.SetMapUnit( nUnits == 1 ? MAP_INCH : MAP_CM );
+ aMap.SetScaleX( Fraction( 1, nHorizontalResolution ) );
+ aMap.SetScaleY( Fraction( 1, nVerticalResolution ) );
+ aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap, MapMode( MAP_100TH_MM ) );
+ }
+ }
+ }
+ }
+ break;
+
+ // Start of Frame Markers
+ case 0xc0 : // SOF0
+ case 0xc1 : // SOF1
+ case 0xc2 : // SOF2
+ case 0xc3 : // SOF3
+ case 0xc5 : // SOF5
+ case 0xc6 : // SOF6
+ case 0xc7 : // SOF7
+ case 0xc9 : // SOF9
+ case 0xca : // SOF10
+ case 0xcb : // SOF11
+ case 0xcd : // SOF13
+ case 0xce : // SOF14
+ case 0xcf : // SOF15
+ {
+ sal_uInt8 nSamplePrecision;
+ sal_uInt16 nNumberOfLines;
+ sal_uInt16 nSamplesPerLine;
+ sal_uInt8 nNumberOfImageComponents;
+ sal_uInt8 nComponentsIdentifier;
+ sal_uInt8 nHorizontalSamplingFactor;
+ sal_uInt8 nQuantizationTableDestinationSelector;
+ rStm >> nSamplePrecision
+ >> nNumberOfLines
+ >> nSamplesPerLine
+ >> nNumberOfImageComponents
+ >> nComponentsIdentifier
+ >> nHorizontalSamplingFactor
+ >> nQuantizationTableDestinationSelector;
+ nHorizontalSamplingFactor >>= 4;
+
+ aPixSize.Height() = nNumberOfLines;
+ aPixSize.Width() = nSamplesPerLine;
+ nBitsPerPixel = ( nNumberOfImageComponents == 3 ? 24 : nNumberOfImageComponents == 1 ? 8 : 0 );
+ nPlanes = 1;
+
+ bScanFinished = sal_True;
+ }
+ break;
+ }
+ rStm.Seek( nNextMarkerPos );
+ }
+ }
+ break;
+ }
+ }
+ rStm.SetError( nError );
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ sal_uInt32 nTemp32;
+ sal_uInt16 nTemp16;
+ sal_uInt8 cByte;
+
+ rStm.SeekRel( 2048 );
+ rStm >> nTemp32;
+ rStm >> nTemp16;
+ rStm >> cByte;
+
+ if ( ( nTemp32 == 0x5f444350 ) &&
+ ( nTemp16 == 0x5049 ) &&
+ ( cByte == 0x49 ) )
+ {
+ nFormat = GFF_PCD;
+ bRet = sal_True;
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPCX( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ // ! Because 0x0a can be interpreted as LF too ...
+ // we cant be shure that this special sign represent a PCX file only.
+ // Every Ascii file is possible here :-(
+ // We must detect the whole header.
+ bExtendedInfo = sal_True;
+
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cByte;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStm >> cByte;
+
+ if ( cByte == 0x0a )
+ {
+ nFormat = GFF_PCX;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uInt16 nTemp16;
+ sal_uInt16 nXmin;
+ sal_uInt16 nXmax;
+ sal_uInt16 nYmin;
+ sal_uInt16 nYmax;
+ sal_uInt16 nDPIx;
+ sal_uInt16 nDPIy;
+
+
+ rStm.SeekRel( 1 );
+
+ // Kompression lesen
+ rStm >> cByte;
+ bCompressed = ( cByte > 0 );
+
+ bRet = (cByte==0 || cByte ==1);
+
+ // Bits/Pixel lesen
+ rStm >> cByte;
+ nBitsPerPixel = cByte;
+
+ // Bildabmessungen
+ rStm >> nTemp16;
+ nXmin = nTemp16;
+ rStm >> nTemp16;
+ nYmin = nTemp16;
+ rStm >> nTemp16;
+ nXmax = nTemp16;
+ rStm >> nTemp16;
+ nYmax = nTemp16;
+
+ aPixSize.Width() = nXmax - nXmin + 1;
+ aPixSize.Height() = nYmax - nYmin + 1;
+
+ // Aufloesung
+ rStm >> nTemp16;
+ nDPIx = nTemp16;
+ rStm >> nTemp16;
+ nDPIy = nTemp16;
+
+ // logische Groesse setzen
+ MapMode aMap( MAP_INCH, Point(),
+ Fraction( 1, nDPIx ), Fraction( 1, nDPIy ) );
+ aLogSize = OutputDevice::LogicToLogic( aPixSize, aMap,
+ MapMode( MAP_100TH_MM ) );
+
+
+ // Anzahl Farbebenen
+ rStm.SeekRel( 49 );
+ rStm >> cByte;
+ nPlanes = cByte;
+
+ bRet = (nPlanes<=4);
+ }
+ }
+
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_uInt32 nTemp32;
+ sal_Bool bRet = sal_False;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStm >> nTemp32;
+
+ if ( nTemp32 == 0x89504e47 )
+ {
+ rStm >> nTemp32;
+ if ( nTemp32 == 0x0d0a1a0a )
+ {
+ nFormat = GFF_PNG;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uInt8 cByte;
+
+ // IHDR-Chunk
+ rStm.SeekRel( 8 );
+
+ // Breite einlesen
+ rStm >> nTemp32;
+ aPixSize.Width() = nTemp32;
+
+ // Hoehe einlesen
+ rStm >> nTemp32;
+ aPixSize.Height() = nTemp32;
+
+ // Bits/Pixel einlesen
+ rStm >> cByte;
+ nBitsPerPixel = cByte;
+
+ // Planes immer 1;
+ // Kompression immer
+ nPlanes = 1;
+ bCompressed = sal_True;
+
+ sal_uInt32 nLen32;
+
+ rStm.SeekRel( 8 );
+
+ // so lange ueberlesen, bis wir den pHYs-Chunk haben oder
+ // den Anfang der Bilddaten
+ rStm >> nLen32;
+ rStm >> nTemp32;
+ while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 ) )
+ {
+ rStm.SeekRel( 4 + nLen32 );
+ rStm >> nLen32;
+ rStm >> nTemp32;
+ }
+
+ if ( nTemp32 == 0x70485973 )
+ {
+ sal_uLong nXRes;
+ sal_uLong nYRes;
+
+ // horizontale Aufloesung
+ rStm >> nTemp32;
+ nXRes = nTemp32;
+
+ // vertikale Aufloesung
+ rStm >> nTemp32;
+ nYRes = nTemp32;
+
+ // Unit einlesen
+ rStm >> cByte;
+
+ if ( cByte )
+ {
+ if ( nXRes )
+ aLogSize.Width() = ( aPixSize.Width() * 100000 ) /
+ nTemp32;
+
+ if ( nYRes )
+ aLogSize.Height() = ( aPixSize.Height() * 100000 ) /
+ nTemp32;
+ }
+ }
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectTIF( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_Bool bDetectOk = sal_False;
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cByte1;
+ sal_uInt8 cByte2;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm >> cByte1;
+ rStm >> cByte2;
+ if ( cByte1 == cByte2 )
+ {
+ if ( cByte1 == 0x49 )
+ {
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ bDetectOk = sal_True;
+ }
+ else if ( cByte1 == 0x4d )
+ {
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ bDetectOk = sal_True;
+ }
+
+ if ( bDetectOk )
+ {
+ sal_uInt16 nTemp16;
+
+ rStm >> nTemp16;
+ if ( nTemp16 == 0x2a )
+ {
+ nFormat = GFF_TIF;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uLong nCount;
+ sal_uLong nMax = DATA_SIZE - 48;
+ sal_uInt32 nTemp32;
+ sal_Bool bOk = sal_False;
+
+ // Offset des ersten IFD einlesen
+ rStm >> nTemp32;
+ rStm.SeekRel( ( nCount = ( nTemp32 + 2 ) ) - 0x08 );
+
+ if ( nCount < nMax )
+ {
+ // Tag's lesen, bis wir auf Tag256 ( Width ) treffen
+ // nicht mehr Bytes als DATA_SIZE lesen
+ rStm >> nTemp16;
+ while ( nTemp16 != 256 )
+ {
+ bOk = nCount < nMax;
+ if ( !bOk )
+ {
+ break;
+ }
+ rStm.SeekRel( 10 );
+ rStm >> nTemp16;
+ nCount += 12;
+ }
+
+ if ( bOk )
+ {
+ // Breite lesen
+ rStm >> nTemp16;
+ rStm.SeekRel( 4 );
+ if ( nTemp16 == 3 )
+ {
+ rStm >> nTemp16;
+ aPixSize.Width() = nTemp16;
+ rStm.SeekRel( 2 );
+ }
+ else
+ {
+ rStm >> nTemp32;
+ aPixSize.Width() = nTemp32;
+ }
+ nCount += 12;
+
+ // Hoehe lesen
+ rStm.SeekRel( 2 );
+ rStm >> nTemp16;
+ rStm.SeekRel( 4 );
+ if ( nTemp16 == 3 )
+ {
+ rStm >> nTemp16;
+ aPixSize.Height() = nTemp16;
+ rStm.SeekRel( 2 );
+ }
+ else
+ {
+ rStm >> nTemp32;
+ aPixSize.Height() = nTemp32;
+ }
+ nCount += 12;
+
+ // ggf. Bits/Pixel lesen
+ rStm >> nTemp16;
+ if ( nTemp16 == 258 )
+ {
+ rStm.SeekRel( 6 );
+ rStm >> nTemp16;
+ nBitsPerPixel = nTemp16;
+ rStm.SeekRel( 2 );
+ nCount += 12;
+ }
+ else
+ rStm.SeekRel( -2 );
+
+ // ggf. Compression lesen
+ rStm >> nTemp16;
+ if ( nTemp16 == 259 )
+ {
+ rStm.SeekRel( 6 );
+ rStm >> nTemp16;
+ bCompressed = ( nTemp16 > 1 );
+ rStm.SeekRel( 2 );
+ nCount += 12;
+ }
+ else
+ rStm.SeekRel( -2 );
+ }
+ }
+ }
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectXBM( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "xbm", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_XBM;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectXPM( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "xpm", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_XPM;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPBM( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+
+ // erst auf Datei Extension pruefen, da diese aussagekraeftiger ist
+ // als die 2 ID Bytes
+
+ if ( aPathExt.CompareToAscii( "pbm", 3 ) == COMPARE_EQUAL )
+ bRet = sal_True;
+ else
+ {
+ sal_Int32 nStmPos = rStm.Tell();
+ sal_uInt8 nFirst, nSecond;
+ rStm >> nFirst >> nSecond;
+ if ( nFirst == 'P' && ( ( nSecond == '1' ) || ( nSecond == '4' ) ) )
+ bRet = sal_True;
+ rStm.Seek( nStmPos );
+ }
+
+ if ( bRet )
+ nFormat = GFF_PBM;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPGM( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( aPathExt.CompareToAscii( "pgm", 3 ) == COMPARE_EQUAL )
+ bRet = sal_True;
+ else
+ {
+ sal_uInt8 nFirst, nSecond;
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm >> nFirst >> nSecond;
+ if ( nFirst == 'P' && ( ( nSecond == '2' ) || ( nSecond == '5' ) ) )
+ bRet = sal_True;
+ rStm.Seek( nStmPos );
+ }
+
+ if ( bRet )
+ nFormat = GFF_PGM;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPPM( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( aPathExt.CompareToAscii( "ppm", 3 ) == COMPARE_EQUAL )
+ bRet = sal_True;
+ else
+ {
+ sal_uInt8 nFirst, nSecond;
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm >> nFirst >> nSecond;
+ if ( nFirst == 'P' && ( ( nSecond == '3' ) || ( nSecond == '6' ) ) )
+ bRet = sal_True;
+ rStm.Seek( nStmPos );
+ }
+
+ if ( bRet )
+ nFormat = GFF_PPM;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectRAS( SvStream& rStm, sal_Bool )
+{
+ sal_uInt32 nMagicNumber;
+ sal_Bool bRet = sal_False;
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStm >> nMagicNumber;
+ if ( nMagicNumber == 0x59a66a95 )
+ {
+ nFormat = GFF_RAS;
+ bRet = sal_True;
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectTGA( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "tga", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_TGA;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectPSD( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_Bool bRet = sal_False;
+
+ sal_uInt32 nMagicNumber;
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStm >> nMagicNumber;
+ if ( nMagicNumber == 0x38425053 )
+ {
+ sal_uInt16 nVersion;
+ rStm >> nVersion;
+ if ( nVersion == 1 )
+ {
+ bRet = sal_True;
+ if ( bExtendedInfo )
+ {
+ sal_uInt16 nChannels;
+ sal_uInt32 nRows;
+ sal_uInt32 nColumns;
+ sal_uInt16 nDepth;
+ sal_uInt16 nMode;
+ rStm.SeekRel( 6 ); // Pad
+ rStm >> nChannels >> nRows >> nColumns >> nDepth >> nMode;
+ if ( ( nDepth == 1 ) || ( nDepth == 8 ) || ( nDepth == 16 ) )
+ {
+ nBitsPerPixel = ( nDepth == 16 ) ? 8 : nDepth;
+ switch ( nChannels )
+ {
+ case 4 :
+ case 3 :
+ nBitsPerPixel = 24;
+ case 2 :
+ case 1 :
+ aPixSize.Width() = nColumns;
+ aPixSize.Height() = nRows;
+ break;
+ default:
+ bRet = sal_False;
+ }
+ }
+ else
+ bRet = sal_False;
+ }
+ }
+ }
+
+ if ( bRet )
+ nFormat = GFF_PSD;
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectEPS( SvStream& rStm, sal_Bool )
+{
+ // es wird die EPS mit Vorschaubild Variante und die Extensionuebereinstimmung
+ // geprueft
+
+ sal_uInt32 nFirstLong;
+ sal_uInt8 nFirstBytes[20];
+ sal_Bool bRet = sal_False;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
+ rStm >> nFirstLong;
+ rStm.SeekRel( -4 );
+ rStm.Read( &nFirstBytes, 20 );
+
+ if ( ( nFirstLong == 0xC5D0D3C6 ) || ( aPathExt.CompareToAscii( "eps", 3 ) == COMPARE_EQUAL ) ||
+ ( ImplSearchEntry( nFirstBytes, (sal_uInt8*)"%!PS-Adobe", 10, 10 )
+ && ImplSearchEntry( &nFirstBytes[15], (sal_uInt8*)"EPS", 3, 3 ) ) )
+ {
+ nFormat = GFF_EPS;
+ bRet = sal_True;
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectDXF( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "dxf", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_DXF;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectMET( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "met", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_MET;
+
+ return bRet;
+}
+
+extern bool isPCT(SvStream& rStream, sal_uLong nStreamPos, sal_uLong nStreamLen);
+
+sal_Bool GraphicDescriptor::ImpDetectPCT( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "pct", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_PCT;
+ else
+ {
+ sal_Size nStreamPos = rStm.Tell();
+ sal_Size nStreamLen = rStm.remainingSize();
+ if (isPCT(rStm, nStreamPos, nStreamLen))
+ {
+ bRet = sal_True;
+ nFormat = GFF_PCT;
+ }
+ rStm.Seek(nStreamPos);
+ }
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectSGF( SvStream& rStm, sal_Bool )
+{
+ sal_Bool bRet = sal_False;
+ if( aPathExt.CompareToAscii( "sgf", 3 ) == COMPARE_EQUAL )
+ bRet = sal_True;
+ else
+ {
+ sal_Int32 nStmPos = rStm.Tell();
+
+ sal_uInt8 nFirst, nSecond;
+
+ rStm >> nFirst >> nSecond;
+
+ if( nFirst == 'J' && nSecond == 'J' )
+ bRet = sal_True;
+
+ rStm.Seek( nStmPos );
+ }
+
+ if( bRet )
+ nFormat = GFF_SGF;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectSGV( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "sgv", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_SGV;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectSVM( SvStream& rStm, sal_Bool bExtendedInfo )
+{
+ sal_uInt32 n32;
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cByte;
+
+ sal_Int32 nStmPos = rStm.Tell();
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStm >> n32;
+ if ( n32 == 0x44475653 )
+ {
+ rStm >> cByte;
+ if ( cByte == 0x49 )
+ {
+ nFormat = GFF_SVM;
+ bRet = sal_True;
+
+ if ( bExtendedInfo )
+ {
+ sal_uInt32 nTemp32;
+ sal_uInt16 nTemp16;
+
+ rStm.SeekRel( 0x04 );
+
+ // Breite auslesen
+ rStm >> nTemp32;
+ aLogSize.Width() = nTemp32;
+
+ // Hoehe auslesen
+ rStm >> nTemp32;
+ aLogSize.Height() = nTemp32;
+
+ // Map-Unit auslesen und PrefSize ermitteln
+ rStm >> nTemp16;
+ aLogSize = OutputDevice::LogicToLogic( aLogSize,
+ MapMode( (MapUnit) nTemp16 ),
+ MapMode( MAP_100TH_MM ) );
+ }
+ }
+ }
+ else
+ {
+ rStm.SeekRel( -4L );
+ rStm >> n32;
+
+ if( n32 == 0x4D4C4356 )
+ {
+ sal_uInt16 nTmp16;
+
+ rStm >> nTmp16;
+
+ if( nTmp16 == 0x4654 )
+ {
+ nFormat = GFF_SVM;
+ bRet = sal_True;
+
+ if( bExtendedInfo )
+ {
+ MapMode aMapMode;
+
+ rStm.SeekRel( 0x06 );
+ rStm >> aMapMode;
+ rStm >> aLogSize;
+ aLogSize = OutputDevice::LogicToLogic( aLogSize, aMapMode, MapMode( MAP_100TH_MM ) );
+ }
+ }
+ }
+ }
+ rStm.Seek( nStmPos );
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectWMF( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "wmf",3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_WMF;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectEMF( SvStream&, sal_Bool )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "emf", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_EMF;
+
+ return bRet;
+}
+
+sal_Bool GraphicDescriptor::ImpDetectSVG( SvStream& /*rStm*/, sal_Bool /*bExtendedInfo*/ )
+{
+ sal_Bool bRet = aPathExt.CompareToAscii( "svg", 3 ) == COMPARE_EQUAL;
+ if (bRet)
+ nFormat = GFF_SVG;
+
+ return bRet;
+}
+
+String GraphicDescriptor::GetImportFormatShortName( sal_uInt16 nFormat )
+{
+ const char *pKeyName = 0;
+
+ switch( nFormat )
+ {
+ case( GFF_BMP ) : pKeyName = "bmp"; break;
+ case( GFF_GIF ) : pKeyName = "gif"; break;
+ case( GFF_JPG ) : pKeyName = "jpg"; break;
+ case( GFF_PCD ) : pKeyName = "pcd"; break;
+ case( GFF_PCX ) : pKeyName = "pcx"; break;
+ case( GFF_PNG ) : pKeyName = "png"; break;
+ case( GFF_XBM ) : pKeyName = "xbm"; break;
+ case( GFF_XPM ) : pKeyName = "xpm"; break;
+ case( GFF_PBM ) : pKeyName = "pbm"; break;
+ case( GFF_PGM ) : pKeyName = "pgm"; break;
+ case( GFF_PPM ) : pKeyName = "ppm"; break;
+ case( GFF_RAS ) : pKeyName = "ras"; break;
+ case( GFF_TGA ) : pKeyName = "tga"; break;
+ case( GFF_PSD ) : pKeyName = "psd"; break;
+ case( GFF_EPS ) : pKeyName = "eps"; break;
+ case( GFF_TIF ) : pKeyName = "tif"; break;
+ case( GFF_DXF ) : pKeyName = "dxf"; break;
+ case( GFF_MET ) : pKeyName = "met"; break;
+ case( GFF_PCT ) : pKeyName = "pct"; break;
+ case( GFF_SGF ) : pKeyName = "sgf"; break;
+ case( GFF_SGV ) : pKeyName = "sgv"; break;
+ case( GFF_SVM ) : pKeyName = "svm"; break;
+ case( GFF_WMF ) : pKeyName = "wmf"; break;
+ case( GFF_EMF ) : pKeyName = "emf"; break;
+ case( GFF_SVG ) : pKeyName = "svg"; break;
+ }
+
+ return rtl::OUString::createFromAscii(pKeyName);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/igif/decode.cxx b/vcl/source/filter/igif/decode.cxx
new file mode 100644
index 000000000000..09981f6e3d28
--- /dev/null
+++ b/vcl/source/filter/igif/decode.cxx
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "decode.hxx"
+
+// ------------------------------------------------------------------------
+
+struct GIFLZWTableEntry
+{
+ GIFLZWTableEntry* pPrev;
+ GIFLZWTableEntry* pFirst;
+ sal_uInt8 nData;
+};
+
+// ------------------------------------------------------------------------
+
+GIFLZWDecompressor::GIFLZWDecompressor( sal_uInt8 cDataSize ) :
+ nInputBitsBuf ( 0 ),
+ nOutBufDataLen ( 0 ),
+ nInputBitsBufSize ( 0 ),
+ bEOIFound ( sal_False ),
+ nDataSize ( cDataSize )
+{
+ pOutBuf = new sal_uInt8[ 4096 ];
+
+ nClearCode = 1 << nDataSize;
+ nEOICode = nClearCode + 1;
+ nTableSize = nEOICode + 1;
+ nCodeSize = nDataSize + 1;
+ nOldCode = 0xffff;
+ pOutBufData = pOutBuf + 4096;
+
+ pTable = new GIFLZWTableEntry[ 4098 ];
+
+ for( sal_uInt16 i = 0; i < nTableSize; i++ )
+ {
+ pTable[i].pPrev = NULL;
+ pTable[i].pFirst = pTable + i;
+ pTable[i].nData = (sal_uInt8) i;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+GIFLZWDecompressor::~GIFLZWDecompressor()
+{
+ delete[] pOutBuf;
+ delete[] pTable;
+}
+
+// ------------------------------------------------------------------------
+
+HPBYTE GIFLZWDecompressor::DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize,
+ sal_uLong& rCount, sal_Bool& rEOI )
+{
+ sal_uLong nTargetSize = 4096;
+ sal_uLong nCount = 0;
+ HPBYTE pTarget = (HPBYTE) rtl_allocateMemory( nTargetSize );
+ HPBYTE pTmpTarget = pTarget;
+
+ nBlockBufSize = cBufSize;
+ nBlockBufPos = 0;
+ pBlockBuf = pSrc;
+
+ while( ProcessOneCode() )
+ {
+ nCount += nOutBufDataLen;
+
+ if( nCount > nTargetSize )
+ {
+ sal_uLong nNewSize = nTargetSize << 1;
+ sal_uLong nOffset = pTmpTarget - pTarget;
+ HPBYTE pTmp = (HPBYTE) rtl_allocateMemory( nNewSize );
+
+ memcpy( pTmp, pTarget, nTargetSize );
+ rtl_freeMemory( pTarget );
+
+ nTargetSize = nNewSize;
+ pTmpTarget = ( pTarget = pTmp ) + nOffset;
+ }
+
+ memcpy( pTmpTarget, pOutBufData, nOutBufDataLen );
+ pTmpTarget += nOutBufDataLen;
+ pOutBufData += nOutBufDataLen;
+ nOutBufDataLen = 0;
+
+ if ( bEOIFound )
+ break;
+ }
+
+ rCount = nCount;
+ rEOI = bEOIFound;
+
+ return pTarget;
+}
+
+// ------------------------------------------------------------------------
+
+void GIFLZWDecompressor::AddToTable( sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData )
+{
+ GIFLZWTableEntry* pE;
+
+ if( nTableSize < 4096 )
+ {
+ pE = pTable + nTableSize;
+ pE->pPrev = pTable + nPrevCode;
+ pE->pFirst = pE->pPrev->pFirst;
+ pE->nData = pTable[ nCodeFirstData ].pFirst->nData;
+ nTableSize++;
+
+ if ( ( nTableSize == (sal_uInt16) (1 << nCodeSize) ) && ( nTableSize < 4096 ) )
+ nCodeSize++;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFLZWDecompressor::ProcessOneCode()
+{
+ GIFLZWTableEntry* pE;
+ sal_uInt16 nCode;
+ sal_Bool bRet = sal_False;
+ sal_Bool bEndOfBlock = sal_False;
+
+ while( nInputBitsBufSize < nCodeSize )
+ {
+ if( nBlockBufPos >= nBlockBufSize )
+ {
+ bEndOfBlock = sal_True;
+ break;
+ }
+
+ nInputBitsBuf |= ( (sal_uLong) pBlockBuf[ nBlockBufPos++ ] ) << nInputBitsBufSize;
+ nInputBitsBufSize += 8;
+ }
+
+ if ( !bEndOfBlock )
+ {
+ // Einen Code aus dem Eingabe-Buffer holen:
+ nCode = sal::static_int_cast< sal_uInt16 >(
+ ( (sal_uInt16) nInputBitsBuf ) & ( ~( 0xffff << nCodeSize ) ));
+ nInputBitsBuf >>= nCodeSize;
+ nInputBitsBufSize = nInputBitsBufSize - nCodeSize;
+
+ if ( nCode < nClearCode )
+ {
+ if ( nOldCode != 0xffff )
+ AddToTable( nOldCode, nCode );
+ }
+ else if ( ( nCode > nEOICode ) && ( nCode <= nTableSize ) )
+ {
+ if ( nCode == nTableSize )
+ AddToTable( nOldCode, nOldCode );
+ else
+ AddToTable( nOldCode, nCode );
+ }
+ else
+ {
+ if ( nCode == nClearCode )
+ {
+ nTableSize = nEOICode + 1;
+ nCodeSize = nDataSize + 1;
+ nOldCode = 0xffff;
+ nOutBufDataLen = 0;
+ }
+ else
+ bEOIFound = sal_True;
+
+ return sal_True;
+ }
+
+ nOldCode = nCode;
+
+ // Zeichen(/-folge) des Codes nCode in den Ausgabe-Buffer schreiben:
+ pE = pTable + nCode;
+ do
+ {
+ nOutBufDataLen++;
+ *(--pOutBufData) = pE->nData;
+ pE = pE->pPrev;
+ }
+ while( pE );
+
+ bRet = sal_True;
+ }
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/igif/decode.hxx b/vcl/source/filter/igif/decode.hxx
new file mode 100644
index 000000000000..44523e44812a
--- /dev/null
+++ b/vcl/source/filter/igif/decode.hxx
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _DECODE_HXX
+#define _DECODE_HXX
+
+#include <vcl/bmpacc.hxx>
+
+struct GIFLZWTableEntry;
+
+class GIFLZWDecompressor
+{
+ GIFLZWTableEntry* pTable;
+ HPBYTE pOutBuf;
+ HPBYTE pOutBufData;
+ HPBYTE pBlockBuf;
+ sal_uLong nInputBitsBuf;
+ sal_uInt16 nTableSize;
+ sal_uInt16 nClearCode;
+ sal_uInt16 nEOICode;
+ sal_uInt16 nCodeSize;
+ sal_uInt16 nOldCode;
+ sal_uInt16 nOutBufDataLen;
+ sal_uInt16 nInputBitsBufSize;
+ sal_Bool bEOIFound;
+ sal_uInt8 nDataSize;
+ sal_uInt8 nBlockBufSize;
+ sal_uInt8 nBlockBufPos;
+
+ void AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData);
+ sal_Bool ProcessOneCode();
+
+
+public:
+
+ GIFLZWDecompressor( sal_uInt8 cDataSize );
+ ~GIFLZWDecompressor();
+
+ HPBYTE DecompressBlock( HPBYTE pSrc, sal_uInt8 cBufSize, sal_uLong& rCount, sal_Bool& rEOI );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/igif/gifread.cxx b/vcl/source/filter/igif/gifread.cxx
new file mode 100644
index 000000000000..733fd9572bc2
--- /dev/null
+++ b/vcl/source/filter/igif/gifread.cxx
@@ -0,0 +1,865 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#define _GIFPRIVATE
+
+#include "decode.hxx"
+#include "gifread.hxx"
+
+// -----------
+// - Defines -
+// -----------
+
+#define NO_PENDING( rStm ) ( ( rStm ).GetError() != ERRCODE_IO_PENDING )
+
+// -------------
+// - GIFReader -
+// -------------
+
+GIFReader::GIFReader( SvStream& rStm ) :
+ aGPalette ( 256 ),
+ aLPalette ( 256 ),
+ rIStm ( rStm ),
+ pAcc8 ( NULL ),
+ pAcc1 ( NULL ),
+ nLastPos ( rStm.Tell() ),
+ nLogWidth100 ( 0UL ),
+ nLogHeight100 ( 0UL ),
+ nGlobalWidth ( 0 ),
+ nGlobalHeight ( 0 ),
+ nImageWidth ( 0 ),
+ nImageHeight ( 0 ),
+ nLoops ( 1 ),
+ eActAction ( GLOBAL_HEADER_READING ),
+ bGCTransparent ( sal_False ),
+ bImGraphicReady ( sal_False )
+{
+ maUpperName = rtl::OUString("SVIGIF");
+ pSrcBuf = new sal_uInt8[ 256 ];
+ ClearImageExtensions();
+}
+
+// ------------------------------------------------------------------------
+
+GIFReader::~GIFReader()
+{
+ aImGraphic.SetContext( NULL );
+
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+
+ if( pAcc8 )
+ aBmp8.ReleaseAccess( pAcc8 );
+
+ delete[] pSrcBuf;
+}
+
+// ------------------------------------------------------------------------
+
+void GIFReader::ClearImageExtensions()
+{
+ nGCDisposalMethod = 0;
+ bGCTransparent = sal_False;
+ nTimer = 0;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFReader::CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal,
+ sal_Bool bWatchForBackgroundColor )
+{
+ const Size aSize( nWidth, nHeight );
+
+#ifdef __LP64__
+ // Don't bother allocating a bitmap of a size that would fail on a
+ // 32-bit system. We have at least one unit tests that is expected
+ // to fail (loading a 65535*65535 size GIF
+ // svtools/qa/cppunit/data/gif/fail/CVE-2008-5937-1.gif), but
+ // which doesn't fail on 64-bit Mac OS X at least. Why the loading
+ // fails on 64-bit Linux, no idea.
+ if (nWidth >= 64000 && nHeight >= 64000)
+ {
+ bStatus = sal_False;
+ return bStatus;
+ }
+#endif
+
+ if( bGCTransparent )
+ {
+ const Color aWhite( COL_WHITE );
+
+ aBmp1 = Bitmap( aSize, 1 );
+
+ if( !aAnimation.Count() )
+ aBmp1.Erase( aWhite );
+
+ pAcc1 = aBmp1.AcquireWriteAccess();
+
+ if( pAcc1 )
+ {
+ cTransIndex1 = (sal_uInt8) pAcc1->GetBestPaletteIndex( aWhite );
+ cNonTransIndex1 = cTransIndex1 ? 0 : 1;
+ }
+ else
+ bStatus = sal_False;
+ }
+
+ if( bStatus )
+ {
+ aBmp8 = Bitmap( aSize, 8, pPal );
+
+ if( !!aBmp8 && bWatchForBackgroundColor && aAnimation.Count() )
+ aBmp8.Erase( (*pPal)[ nBackgroundColor ] );
+ else
+ aBmp8.Erase( Color( COL_WHITE ) );
+
+ pAcc8 = aBmp8.AcquireWriteAccess();
+ bStatus = ( pAcc8 != NULL );
+ }
+
+ return bStatus;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFReader::ReadGlobalHeader()
+{
+ char pBuf[ 7 ];
+ sal_uInt8 nRF;
+ sal_uInt8 nAspect;
+ sal_Bool bRet = sal_False;
+
+ rIStm.Read( pBuf, 6 );
+ if( NO_PENDING( rIStm ) )
+ {
+ pBuf[ 6 ] = 0;
+ if( !strcmp( pBuf, "GIF87a" ) || !strcmp( pBuf, "GIF89a" ) )
+ {
+ rIStm.Read( pBuf, 7 );
+ if( NO_PENDING( rIStm ) )
+ {
+ SvMemoryStream aMemStm;
+
+ aMemStm.SetBuffer( pBuf, 7, sal_False, 7 );
+ aMemStm >> nGlobalWidth;
+ aMemStm >> nGlobalHeight;
+ aMemStm >> nRF;
+ aMemStm >> nBackgroundColor;
+ aMemStm >> nAspect;
+
+ bGlobalPalette = (sal_Bool) ( nRF & 0x80 );
+
+ if( bGlobalPalette )
+ ReadPaletteEntries( &aGPalette, 1 << ( ( nRF & 7 ) + 1 ) );
+ else
+ nBackgroundColor = 0;
+
+ if( NO_PENDING( rIStm ) )
+ bRet = sal_True;
+ }
+ }
+ else
+ bStatus = sal_False;
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GIFReader::ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount )
+{
+ const sal_uLong nLen = 3UL * nCount;
+ sal_uInt8* pBuf = new sal_uInt8[ nLen ];
+
+ rIStm.Read( pBuf, nLen );
+ if( NO_PENDING( rIStm ) )
+ {
+ sal_uInt8* pTmp = pBuf;
+
+ for( sal_uLong i = 0UL; i < nCount; )
+ {
+ BitmapColor& rColor = (*pPal)[ (sal_uInt16) i++ ];
+
+ rColor.SetRed( *pTmp++ );
+ rColor.SetGreen( *pTmp++ );
+ rColor.SetBlue( *pTmp++ );
+ }
+
+ // nach Moeglichkeit noch einige Standardfarben unterbringen
+ if( nCount < 256UL )
+ {
+ (*pPal)[ 255UL ] = Color( COL_WHITE );
+
+ if( nCount < 255UL )
+ (*pPal)[ 254UL ] = Color( COL_BLACK );
+ }
+ }
+
+ delete[] pBuf;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFReader::ReadExtension()
+{
+ sal_uInt8 cFunction;
+ sal_uInt8 cSize;
+ sal_uInt8 cByte;
+ sal_Bool bRet = sal_False;
+ sal_Bool bOverreadDataBlocks = sal_False;
+
+ // Extension-Label
+ rIStm >> cFunction;
+ if( NO_PENDING( rIStm ) )
+ {
+ // Block-Laenge
+ rIStm >> cSize;
+
+ switch( cFunction )
+ {
+ // 'Graphic Control Extension'
+ case( 0xf9 ) :
+ {
+ sal_uInt8 cFlags;
+
+ rIStm >> cFlags;
+ rIStm >> nTimer;
+ rIStm >> nGCTransparentIndex;
+ rIStm >> cByte;
+
+ if ( NO_PENDING( rIStm ) )
+ {
+ nGCDisposalMethod = ( cFlags >> 2) & 7;
+ bGCTransparent = ( cFlags & 1 ) ? sal_True : sal_False;
+ bStatus = ( cSize == 4 ) && ( cByte == 0 );
+ bRet = sal_True;
+ }
+ }
+ break;
+
+ // Application-Extension
+ case ( 0xff ) :
+ {
+ if ( NO_PENDING( rIStm ) )
+ {
+ // default diese Extension ueberlesen
+ bOverreadDataBlocks = sal_True;
+
+ // Appl.-Extension hat Laenge 11
+ if ( cSize == 0x0b )
+ {
+ rtl::OString aAppId = read_uInt8s_ToOString(rIStm, 8);
+ rtl::OString aAppCode = read_uInt8s_ToOString(rIStm, 3);
+ rIStm >> cSize;
+
+ // NetScape-Extension
+ if( aAppId.equalsL(RTL_CONSTASCII_STRINGPARAM("NETSCAPE")) && aAppCode.equalsL(RTL_CONSTASCII_STRINGPARAM("2.0")) && cSize == 3 )
+ {
+ rIStm >> cByte;
+
+ // Loop-Extension
+ if ( cByte == 0x01 )
+ {
+ rIStm >> cByte;
+ nLoops = cByte;
+ rIStm >> cByte;
+ nLoops |= ( (sal_uInt16) cByte << 8 );
+ rIStm >> cByte;
+
+ bStatus = ( cByte == 0 );
+ bRet = NO_PENDING( rIStm );
+ bOverreadDataBlocks = sal_False;
+
+ // Netscape interpretiert den LoopCount
+ // als reine Anzahl der _Wiederholungen_;
+ // bei uns ist es die Gesamtanzahl der
+ // Durchlaeufe
+ if( nLoops )
+ nLoops++;
+ }
+ else
+ rIStm.SeekRel( -1 );
+ }
+ else if ( aAppId.equalsL(RTL_CONSTASCII_STRINGPARAM("STARDIV ")) && aAppCode.equalsL(RTL_CONSTASCII_STRINGPARAM("5.0")) && cSize == 9 )
+ {
+ rIStm >> cByte;
+
+ // Loop-Extension
+ if ( cByte == 0x01 )
+ {
+ rIStm >> nLogWidth100 >> nLogHeight100;
+ rIStm >> cByte;
+ bStatus = ( cByte == 0 );
+ bRet = NO_PENDING( rIStm );
+ bOverreadDataBlocks = sal_False;
+ }
+ else
+ rIStm.SeekRel( -1 );
+ }
+
+ }
+ }
+ }
+ break;
+
+ // alles andere ueberlesen
+ default:
+ bOverreadDataBlocks = sal_True;
+ break;
+ }
+
+ // Sub-Blocks ueberlesen
+ if ( bOverreadDataBlocks )
+ {
+ bRet = sal_True;
+ while( cSize && bStatus && !rIStm.IsEof() )
+ {
+ sal_uInt16 nCount = (sal_uInt16) cSize + 1;
+ char* pBuffer = new char[ nCount ];
+
+ bRet = sal_False;
+ rIStm.Read( pBuffer, nCount );
+ if( NO_PENDING( rIStm ) )
+ {
+ cSize = (sal_uInt8) pBuffer[ cSize ];
+ bRet = sal_True;
+ }
+ else
+ cSize = 0;
+
+ delete[] pBuffer;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFReader::ReadLocalHeader()
+{
+ sal_uInt8 pBuf[ 9 ];
+ sal_Bool bRet = sal_False;
+
+ rIStm.Read( pBuf, 9 );
+ if( NO_PENDING( rIStm ) )
+ {
+ SvMemoryStream aMemStm;
+ BitmapPalette* pPal;
+ sal_uInt8 nFlags;
+
+ aMemStm.SetBuffer( (char*) pBuf, 9, sal_False, 9 );
+ aMemStm >> nImagePosX;
+ aMemStm >> nImagePosY;
+ aMemStm >> nImageWidth;
+ aMemStm >> nImageHeight;
+ aMemStm >> nFlags;
+
+ // Falls Interlaced, ersten Startwert vorgeben
+ bInterlaced = ( ( nFlags & 0x40 ) == 0x40 );
+ nLastInterCount = 7;
+ nLastImageY = 0;
+
+ if( nFlags & 0x80 )
+ {
+ pPal = &aLPalette;
+ ReadPaletteEntries( pPal, 1 << ( (nFlags & 7 ) + 1 ) );
+ }
+ else
+ pPal = &aGPalette;
+
+ // Falls alles soweit eingelesen werden konnte, kann
+ // nun das lokale Bild angelegt werden;
+ // es wird uebergeben, ob der BackgroundColorIndex evtl.
+ // beruecksichtigt werden soll ( wenn Globale Farbtab. und
+ // diese auch fuer dieses Bild gilt )
+ if( NO_PENDING( rIStm ) )
+ {
+ CreateBitmaps( nImageWidth, nImageHeight, pPal, bGlobalPalette && ( pPal == &aGPalette ) );
+ bRet = sal_True;
+ }
+ }
+
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+
+sal_uLong GIFReader::ReadNextBlock()
+{
+ sal_uLong nRet = 0UL;
+ sal_uLong nRead;
+ sal_uInt8 cBlockSize;
+
+ rIStm >> cBlockSize;
+
+ if ( rIStm.IsEof() )
+ nRet = 4UL;
+ else if ( NO_PENDING( rIStm ) )
+ {
+ if ( cBlockSize == 0 )
+ nRet = 2UL;
+ else
+ {
+ rIStm.Read( pSrcBuf, cBlockSize );
+
+ if( NO_PENDING( rIStm ) )
+ {
+ if( bOverreadBlock )
+ nRet = 3UL;
+ else
+ {
+ sal_Bool bEOI;
+ HPBYTE pTarget = pDecomp->DecompressBlock( pSrcBuf, cBlockSize, nRead, bEOI );
+
+ nRet = ( bEOI ? 3 : 1 );
+
+ if( nRead && !bOverreadBlock )
+ FillImages( pTarget, nRead );
+
+ rtl_freeMemory( pTarget );
+ }
+ }
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+void GIFReader::FillImages( HPBYTE pBytes, sal_uLong nCount )
+{
+ for( sal_uLong i = 0UL; i < nCount; i++ )
+ {
+ if( nImageX >= nImageWidth )
+ {
+ if( bInterlaced )
+ {
+ long nT1, nT2;
+
+ // falls Interlaced, werden die Zeilen kopiert
+ if( nLastInterCount )
+ {
+ long nMinY = Min( (long) nLastImageY + 1, (long) nImageHeight - 1 );
+ long nMaxY = Min( (long) nLastImageY + nLastInterCount, (long) nImageHeight - 1 );
+
+ // letzte gelesene Zeile kopieren, wenn Zeilen
+ // nicht zusanmmenfallen ( kommt vorm wenn wir am Ende des Bildes sind )
+ if( ( nMinY > nLastImageY ) && ( nLastImageY < ( nImageHeight - 1 ) ) )
+ {
+ HPBYTE pScanline8 = pAcc8->GetScanline( nYAcc );
+ sal_uLong nSize8 = pAcc8->GetScanlineSize();
+ HPBYTE pScanline1 = 0;
+ sal_uLong nSize1 = 0;
+
+ if( bGCTransparent )
+ {
+ pScanline1 = pAcc1->GetScanline( nYAcc );
+ nSize1 = pAcc1->GetScanlineSize();
+ }
+
+ for( long j = nMinY; j <= nMaxY; j++ )
+ {
+ memcpy( pAcc8->GetScanline( j ), pScanline8, nSize8 );
+
+ if( bGCTransparent )
+ memcpy( pAcc1->GetScanline( j ), pScanline1, nSize1 );
+ }
+ }
+ }
+
+ nT1 = ( ++nImageY ) << 3;
+ nLastInterCount = 7;
+
+ if( nT1 >= nImageHeight )
+ {
+ nT2 = nImageY - ( ( nImageHeight + 7 ) >> 3 );
+ nT1 = ( nT2 << 3 ) + 4;
+ nLastInterCount = 3;
+
+ if( nT1 >= nImageHeight )
+ {
+ nT2 -= ( nImageHeight + 3 ) >> 3;
+ nT1 = ( nT2 << 2 ) + 2;
+ nLastInterCount = 1;
+
+ if( nT1 >= nImageHeight )
+ {
+ nT2 -= ( nImageHeight + 1 ) >> 2;
+ nT1 = ( nT2 << 1 ) + 1;
+ nLastInterCount = 0;
+ }
+ }
+ }
+
+ nLastImageY = (sal_uInt16) nT1;
+ nYAcc = nT1;
+ }
+ else
+ {
+ nLastImageY = ++nImageY;
+ nYAcc = nImageY;
+ }
+
+ // Zeile faengt von vorne an
+ nImageX = 0;
+ }
+
+ if( nImageY < nImageHeight )
+ {
+ const sal_uInt8 cTmp = pBytes[ i ];
+
+ if( bGCTransparent )
+ {
+ if( cTmp == nGCTransparentIndex )
+ pAcc1->SetPixel( nYAcc, nImageX++, cTransIndex1 );
+ else
+ {
+ pAcc8->SetPixel( nYAcc, nImageX, cTmp );
+ pAcc1->SetPixel( nYAcc, nImageX++, cNonTransIndex1 );
+ }
+ }
+ else
+ pAcc8->SetPixel( nYAcc, nImageX++, cTmp );
+ }
+ else
+ {
+ bOverreadBlock = sal_True;
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void GIFReader::CreateNewBitmaps()
+{
+ AnimationBitmap aAnimBmp;
+
+ aBmp8.ReleaseAccess( pAcc8 );
+ pAcc8 = NULL;
+
+ if( bGCTransparent )
+ {
+ aBmp1.ReleaseAccess( pAcc1 );
+ pAcc1 = NULL;
+ aAnimBmp.aBmpEx = BitmapEx( aBmp8, aBmp1 );
+ }
+ else
+ aAnimBmp.aBmpEx = BitmapEx( aBmp8 );
+
+ aAnimBmp.aPosPix = Point( nImagePosX, nImagePosY );
+ aAnimBmp.aSizePix = Size( nImageWidth, nImageHeight );
+ aAnimBmp.nWait = ( nTimer != 65535 ) ? nTimer : ANIMATION_TIMEOUT_ON_CLICK;
+ aAnimBmp.bUserInput = sal_False;
+
+ if( nGCDisposalMethod == 2 )
+ aAnimBmp.eDisposal = DISPOSE_BACK;
+ else if( nGCDisposalMethod == 3 )
+ aAnimBmp.eDisposal = DISPOSE_PREVIOUS;
+ else
+ aAnimBmp.eDisposal = DISPOSE_NOT;
+
+ aAnimation.Insert( aAnimBmp );
+
+ if( aAnimation.Count() == 1 )
+ {
+ aAnimation.SetDisplaySizePixel( Size( nGlobalWidth, nGlobalHeight ) );
+ aAnimation.SetLoopCount( nLoops );
+ }
+}
+
+// ------------------------------------------------------------------------
+
+const Graphic& GIFReader::GetIntermediateGraphic()
+{
+ // Intermediate-Graphic nur erzeugen, wenn schon
+ // Daten vorliegen, aber die Graphic noch nicht
+ // vollstaendig eingelesen wurde
+ if ( bImGraphicReady && !aAnimation.Count() )
+ {
+ Bitmap aBmp;
+
+ aBmp8.ReleaseAccess( pAcc8 );
+
+ if ( bGCTransparent )
+ {
+ aBmp1.ReleaseAccess( pAcc1 );
+ aImGraphic = BitmapEx( aBmp8, aBmp1 );
+
+ pAcc1 = aBmp1.AcquireWriteAccess();
+ bStatus = bStatus && ( pAcc1 != NULL );
+ }
+ else
+ aImGraphic = aBmp8;
+
+ pAcc8 = aBmp8.AcquireWriteAccess();
+ bStatus = bStatus && ( pAcc8 != NULL );
+ }
+
+ return aImGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool GIFReader::ProcessGIF()
+{
+ sal_Bool bRead = sal_False;
+ sal_Bool bEnd = sal_False;
+
+ if ( !bStatus )
+ eActAction = ABORT_READING;
+
+ // Stream an die richtige Stelle bringen
+ rIStm.Seek( nLastPos );
+
+ switch( eActAction )
+ {
+ // naechsten Marker lesen
+ case( MARKER_READING ):
+ {
+ sal_uInt8 cByte;
+
+ rIStm >> cByte;
+
+ if( rIStm.IsEof() )
+ eActAction = END_READING;
+ else if( NO_PENDING( rIStm ) )
+ {
+ bRead = sal_True;
+
+ if( cByte == '!' )
+ eActAction = EXTENSION_READING;
+ else if( cByte == ',' )
+ eActAction = LOCAL_HEADER_READING;
+ else if( cByte == ';' )
+ eActAction = END_READING;
+ else
+ eActAction = ABORT_READING;
+ }
+ }
+ break;
+
+ // ScreenDescriptor lesen
+ case( GLOBAL_HEADER_READING ):
+ {
+ if( ( bRead = ReadGlobalHeader() ) == sal_True )
+ {
+ ClearImageExtensions();
+ eActAction = MARKER_READING;
+ }
+ }
+ break;
+
+
+ // Extension lesen
+ case( EXTENSION_READING ):
+ {
+ if( ( bRead = ReadExtension() ) == sal_True )
+ eActAction = MARKER_READING;
+ }
+ break;
+
+
+ // Image-Descriptor lesen
+ case( LOCAL_HEADER_READING ):
+ {
+ if( ( bRead = ReadLocalHeader() ) == sal_True )
+ {
+ nYAcc = nImageX = nImageY = 0;
+ eActAction = FIRST_BLOCK_READING;
+ }
+ }
+ break;
+
+
+ // ersten Datenblock lesen
+ case( FIRST_BLOCK_READING ):
+ {
+ sal_uInt8 cDataSize;
+
+ rIStm >> cDataSize;
+
+ if( rIStm.IsEof() )
+ eActAction = ABORT_READING;
+ else if( cDataSize > 12 )
+ bStatus = sal_False;
+ else if( NO_PENDING( rIStm ) )
+ {
+ bRead = sal_True;
+ pDecomp = new GIFLZWDecompressor( cDataSize );
+ eActAction = NEXT_BLOCK_READING;
+ bOverreadBlock = sal_False;
+ }
+ else
+ eActAction = FIRST_BLOCK_READING;
+ }
+ break;
+
+ // naechsten Datenblock lesen
+ case( NEXT_BLOCK_READING ):
+ {
+ sal_uInt16 nLastX = nImageX;
+ sal_uInt16 nLastY = nImageY;
+ sal_uLong nRet = ReadNextBlock();
+
+ // Return: 0:Pending / 1:OK; / 2:OK und letzter Block: / 3:EOI / 4:HardAbort
+ if( nRet )
+ {
+ bRead = sal_True;
+
+ if ( nRet == 1UL )
+ {
+ bImGraphicReady = sal_True;
+ eActAction = NEXT_BLOCK_READING;
+ bOverreadBlock = sal_False;
+ }
+ else
+ {
+ if( nRet == 2UL )
+ {
+ delete pDecomp;
+ CreateNewBitmaps();
+ eActAction = MARKER_READING;
+ ClearImageExtensions();
+ }
+ else if( nRet == 3UL )
+ {
+ eActAction = NEXT_BLOCK_READING;
+ bOverreadBlock = sal_True;
+ }
+ else
+ {
+ delete pDecomp;
+ CreateNewBitmaps();
+ eActAction = ABORT_READING;
+ ClearImageExtensions();
+ }
+ }
+ }
+ else
+ {
+ nImageX = nLastX;
+ nImageY = nLastY;
+ }
+ }
+ break;
+
+ // ein Fehler trat auf
+ case( ABORT_READING ):
+ {
+ bEnd = sal_True;
+ eActAction = END_READING;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // Stream an die richtige Stelle bringen,
+ // falls Daten gelesen werden konnten
+ // entweder alte Position oder aktuelle Position
+ if( bRead || bEnd )
+ nLastPos = rIStm.Tell();
+
+ return bRead;
+}
+
+// ------------------------------------------------------------------------
+
+ReadState GIFReader::ReadGIF( Graphic& rGraphic )
+{
+ ReadState eReadState;
+
+ bStatus = sal_True;
+
+ while( ProcessGIF() && ( eActAction != END_READING ) ) {}
+
+ if( !bStatus )
+ eReadState = GIFREAD_ERROR;
+ else if( eActAction == END_READING )
+ eReadState = GIFREAD_OK;
+ else
+ {
+ if ( rIStm.GetError() == ERRCODE_IO_PENDING )
+ rIStm.ResetError();
+
+ eReadState = GIFREAD_NEED_MORE;
+ }
+
+ if( aAnimation.Count() == 1 )
+ {
+ rGraphic = aAnimation.Get( 0 ).aBmpEx;
+
+ if( nLogWidth100 && nLogHeight100 )
+ {
+ rGraphic.SetPrefSize( Size( nLogWidth100, nLogHeight100 ) );
+ rGraphic.SetPrefMapMode( MAP_100TH_MM );
+ }
+ }
+ else
+ rGraphic = aAnimation;
+
+ return eReadState;
+}
+
+
+// -------------
+// - ImportGIF -
+// -------------
+
+sal_Bool ImportGIF( SvStream & rStm, Graphic& rGraphic )
+{
+ GIFReader* pGIFReader = (GIFReader*) rGraphic.GetContext();
+ sal_uInt16 nOldFormat = rStm.GetNumberFormatInt();
+ ReadState eReadState;
+ sal_Bool bRet = sal_True;
+
+ rStm.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ if( !pGIFReader )
+ pGIFReader = new GIFReader( rStm );
+
+ rGraphic.SetContext( NULL );
+ eReadState = pGIFReader->ReadGIF( rGraphic );
+
+ if( eReadState == GIFREAD_ERROR )
+ {
+ bRet = sal_False;
+ delete pGIFReader;
+ }
+ else if( eReadState == GIFREAD_OK )
+ delete pGIFReader;
+ else
+ {
+ rGraphic = pGIFReader->GetIntermediateGraphic();
+ rGraphic.SetContext( pGIFReader );
+ }
+
+ rStm.SetNumberFormatInt( nOldFormat );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/igif/gifread.hxx b/vcl/source/filter/igif/gifread.hxx
new file mode 100644
index 000000000000..35d9b3aa250d
--- /dev/null
+++ b/vcl/source/filter/igif/gifread.hxx
@@ -0,0 +1,133 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _GIFREAD_HXX
+#define _GIFREAD_HXX
+
+#include <vcl/graph.hxx>
+#include <vcl/bmpacc.hxx>
+
+#ifdef _GIFPRIVATE
+
+// ---------
+// - Enums -
+// ---------
+
+enum GIFAction
+{
+ GLOBAL_HEADER_READING,
+ MARKER_READING,
+ EXTENSION_READING,
+ LOCAL_HEADER_READING,
+ FIRST_BLOCK_READING,
+ NEXT_BLOCK_READING,
+ ABORT_READING,
+ END_READING
+};
+
+// ------------------------------------------------------------------------
+
+enum ReadState
+{
+ GIFREAD_OK,
+ GIFREAD_ERROR,
+ GIFREAD_NEED_MORE
+};
+
+// -------------
+// - GIFReader -
+// -------------
+
+class GIFLZWDecompressor;
+
+class SvStream;
+
+class GIFReader : public GraphicReader
+{
+ Graphic aImGraphic;
+ Animation aAnimation;
+ Bitmap aBmp8;
+ Bitmap aBmp1;
+ BitmapPalette aGPalette;
+ BitmapPalette aLPalette;
+ SvStream& rIStm;
+ HPBYTE pSrcBuf;
+ GIFLZWDecompressor* pDecomp;
+ BitmapWriteAccess* pAcc8;
+ BitmapWriteAccess* pAcc1;
+ long nYAcc;
+ long nLastPos;
+ sal_uInt32 nLogWidth100;
+ sal_uInt32 nLogHeight100;
+ sal_uInt16 nTimer;
+ sal_uInt16 nGlobalWidth; // maximale Bildbreite aus Header
+ sal_uInt16 nGlobalHeight; // maximale Bildhoehe aus Header
+ sal_uInt16 nImageWidth; // maximale Bildbreite aus Header
+ sal_uInt16 nImageHeight; // maximale Bildhoehe aus Header
+ sal_uInt16 nImagePosX;
+ sal_uInt16 nImagePosY;
+ sal_uInt16 nImageX; // maximale Bildbreite aus Header
+ sal_uInt16 nImageY; // maximale Bildhoehe aus Header
+ sal_uInt16 nLastImageY;
+ sal_uInt16 nLastInterCount;
+ sal_uInt16 nLoops;
+ GIFAction eActAction;
+ sal_Bool bStatus;
+ sal_Bool bGCTransparent; // Ob das Bild Transparent ist, wenn ja:
+ sal_Bool bInterlaced;
+ sal_Bool bOverreadBlock;
+ sal_Bool bImGraphicReady;
+ sal_Bool bGlobalPalette;
+ sal_uInt8 nBackgroundColor; // Hintergrundfarbe
+ sal_uInt8 nGCTransparentIndex; // Pixel von diesem Index sind durchsichtig
+ sal_uInt8 nGCDisposalMethod; // 'Disposal Method' (siehe GIF-Doku)
+ sal_uInt8 cTransIndex1;
+ sal_uInt8 cNonTransIndex1;
+
+ void ReadPaletteEntries( BitmapPalette* pPal, sal_uLong nCount );
+ void ClearImageExtensions();
+ sal_Bool CreateBitmaps( long nWidth, long nHeight, BitmapPalette* pPal, sal_Bool bWatchForBackgroundColor );
+ sal_Bool ReadGlobalHeader();
+ sal_Bool ReadExtension();
+ sal_Bool ReadLocalHeader();
+ sal_uLong ReadNextBlock();
+ void FillImages( HPBYTE pBytes, sal_uLong nCount );
+ void CreateNewBitmaps();
+ sal_Bool ProcessGIF();
+
+public:
+
+ ReadState ReadGIF( Graphic& rGraphic );
+ const Graphic& GetIntermediateGraphic();
+
+ GIFReader( SvStream& rStm );
+ virtual ~GIFReader();
+};
+
+#endif // _GIFPRIVATE
+
+// -------------
+// - ImportGIF -
+// -------------
+
+ sal_Bool ImportGIF( SvStream& rStream, Graphic& rGraphic );
+
+#endif // _GIFREAD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/ixbm/xbmread.cxx b/vcl/source/filter/ixbm/xbmread.cxx
new file mode 100644
index 000000000000..762c6adee913
--- /dev/null
+++ b/vcl/source/filter/ixbm/xbmread.cxx
@@ -0,0 +1,385 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#define _XBMPRIVATE
+#include <ctype.h>
+#include <comphelper/string.hxx>
+#include "xbmread.hxx"
+
+// -------------
+// - XBMReader -
+// -------------
+
+XBMReader::XBMReader( SvStream& rStm ) :
+ rIStm ( rStm ),
+ pAcc1 ( NULL ),
+ nLastPos ( rStm.Tell() ),
+ nWidth ( 0 ),
+ nHeight ( 0 ),
+ bStatus ( sal_True )
+{
+ pHexTable = new short[ 256 ];
+ maUpperName = rtl::OUString("SVIXBM");
+ InitTable();
+}
+
+// ------------------------------------------------------------------------
+
+XBMReader::~XBMReader()
+{
+ delete[] pHexTable;
+
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+}
+
+// ------------------------------------------------------------------------
+
+void XBMReader::InitTable()
+{
+ memset( pHexTable, 0, sizeof( short ) * 256 );
+
+ pHexTable[(int)'0'] = 0;
+ pHexTable[(int)'1'] = 1;
+ pHexTable[(int)'2'] = 2;
+ pHexTable[(int)'3'] = 3;
+ pHexTable[(int)'4'] = 4;
+ pHexTable[(int)'5'] = 5;
+ pHexTable[(int)'6'] = 6;
+ pHexTable[(int)'7'] = 7;
+ pHexTable[(int)'8'] = 8;
+ pHexTable[(int)'9'] = 9;
+ pHexTable[(int)'A'] = 10;
+ pHexTable[(int)'B'] = 11;
+ pHexTable[(int)'C'] = 12;
+ pHexTable[(int)'D'] = 13;
+ pHexTable[(int)'E'] = 14;
+ pHexTable[(int)'F'] = 15;
+ pHexTable[(int)'X'] = 0;
+ pHexTable[(int)'a'] = 10;
+ pHexTable[(int)'b'] = 11;
+ pHexTable[(int)'c'] = 12;
+ pHexTable[(int)'d'] = 13;
+ pHexTable[(int)'e'] = 14;
+ pHexTable[(int)'f'] = 15;
+ pHexTable[(int)'x'] = 0;
+ pHexTable[(int)' '] = -1;
+ pHexTable[(int)','] = -1;
+ pHexTable[(int)'}'] = -1;
+ pHexTable[(int)'\n'] = -1;
+ pHexTable[(int)'\t'] = -1;
+ pHexTable[(int)'\0'] = -1;
+}
+
+// ------------------------------------------------------------------------
+
+rtl::OString XBMReader::FindTokenLine( SvStream* pInStm, const char* pTok1,
+ const char* pTok2, const char* pTok3 )
+{
+ rtl::OString aRet;
+ sal_Int32 nPos1, nPos2, nPos3;
+
+ bStatus = sal_False;
+
+ do
+ {
+ if( !pInStm->ReadLine( aRet ) )
+ break;
+
+ if( pTok1 )
+ {
+ if( ( nPos1 = aRet.indexOf( pTok1 ) ) != -1 )
+ {
+ bStatus = sal_True;
+
+ if( pTok2 )
+ {
+ bStatus = sal_False;
+
+ if( ( ( nPos2 = aRet.indexOf( pTok2 ) ) != -1 ) &&
+ ( nPos2 > nPos1 ) )
+ {
+ bStatus = sal_True;
+
+ if( pTok3 )
+ {
+ bStatus = sal_False;
+
+ if( ( ( nPos3 = aRet.indexOf( pTok3 ) ) != -1 ) && ( nPos3 > nPos2 ) )
+ bStatus = sal_True;
+ }
+ }
+ }
+ }
+ }
+ }
+ while( !bStatus );
+
+ return aRet;
+}
+
+// ------------------------------------------------------------------------
+
+long XBMReader::ParseDefine( const sal_Char* pDefine )
+{
+ long nRet = 0;
+ char* pTmp = (char*) pDefine;
+ unsigned char cTmp;
+
+ // bis zum Ende gehen
+ pTmp += ( strlen( pDefine ) - 1 );
+ cTmp = *pTmp--;
+
+ // letzte Ziffer suchen
+ while( pHexTable[ cTmp ] == -1 )
+ cTmp = *pTmp--;
+
+ // bis vor die Zahl laufen
+ while( pHexTable[ cTmp ] != -1 )
+ cTmp = *pTmp--;
+
+ // auf Anfang der Zahl gehen
+ pTmp += 2;
+
+ // Hex lesen
+ if( ( pTmp[0] == '0' ) && ( ( pTmp[1] == 'X' ) || ( pTmp[1] == 'x' ) ) )
+ {
+ pTmp += 2;
+ cTmp = *pTmp++;
+
+ while ( pHexTable[ cTmp ] != -1 )
+ {
+ nRet = ( nRet << 4 ) + pHexTable[ cTmp ];
+ cTmp = *pTmp++;
+ }
+ }
+ // Dezimal lesen
+ else
+ {
+ cTmp = *pTmp++;
+ while( ( cTmp >= '0' ) && ( cTmp <= '9' ) )
+ {
+ nRet = nRet * 10 + ( cTmp - '0' );
+ cTmp = *pTmp++;
+ }
+ }
+
+ return nRet;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool XBMReader::ParseData( SvStream* pInStm, const rtl::OString& aLastLine, XBMFormat eFormat )
+{
+ rtl::OString aLine;
+ long nRow = 0;
+ long nCol = 0;
+ long nBits = ( eFormat == XBM10 ) ? 16 : 8;
+ long nBit;
+ sal_uInt16 nValue;
+ sal_uInt16 nDigits;
+ sal_Bool bFirstLine = sal_True;
+
+ while( nRow < nHeight )
+ {
+ if( bFirstLine )
+ {
+ sal_Int32 nPos;
+
+ // einfuehrende geschweifte Klammer loeschen
+ if( (nPos = ( aLine = aLastLine ).indexOf('{') ) != -1 )
+ aLine = aLine.copy(nPos + 1);
+
+ bFirstLine = sal_False;
+ }
+ else if( !pInStm->ReadLine( aLine ) )
+ break;
+
+ if (!aLine.isEmpty())
+ {
+ const sal_Int32 nCount = comphelper::string::getTokenCount(aLine, ',');
+
+ for( sal_Int32 i = 0; ( i < nCount ) && ( nRow < nHeight ); ++i )
+ {
+ const rtl::OString aToken(comphelper::string::getToken(aLine,i, ','));
+ const sal_Int32 nLen = aToken.getLength();
+ sal_Bool bProcessed = sal_False;
+
+ nBit = nDigits = nValue = 0;
+
+ for (sal_Int32 n = 0; n < nLen; ++n)
+ {
+ const unsigned char cChar = aToken[n];
+ const short nTable = pHexTable[ cChar ];
+
+ if( isxdigit( cChar ) || !nTable )
+ {
+ nValue = ( nValue << 4 ) + nTable;
+ nDigits++;
+ bProcessed = sal_True;
+ }
+ else if( ( nTable < 0 ) && nDigits )
+ {
+ bProcessed = sal_True;
+ break;
+ }
+ }
+
+ if( bProcessed )
+ {
+ while( ( nCol < nWidth ) && ( nBit < nBits ) )
+ pAcc1->SetPixel( nRow, nCol++, ( nValue & ( 1 << nBit++ ) ) ? aBlack : aWhite );
+
+ if( nCol == nWidth )
+ nCol = 0, nRow++;
+ }
+ }
+ }
+ }
+
+ return sal_True;
+}
+
+// ------------------------------------------------------------------------
+
+ReadState XBMReader::ReadXBM( Graphic& rGraphic )
+{
+ ReadState eReadState;
+ sal_uInt8 cDummy;
+
+ // sehen, ob wir _alles_ lesen koennen
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ rIStm >> cDummy;
+
+ // falls wir nicht alles lesen koennen
+ // kehren wir zurueck und warten auf neue Daten
+ if ( rIStm.GetError() != ERRCODE_IO_PENDING )
+ {
+ rIStm.Seek( nLastPos );
+ bStatus = sal_False;
+ rtl::OString aLine = FindTokenLine( &rIStm, "#define", "_width" );
+
+ if ( bStatus )
+ {
+ int nValue;
+ if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
+ {
+ nWidth = nValue;
+ aLine = FindTokenLine( &rIStm, "#define", "_height" );
+
+ // Falls die Hoehe nicht folgt, suchen wir noch
+ // einmal vom Anfang der Datei an
+ if ( !bStatus )
+ {
+ rIStm.Seek( nLastPos );
+ aLine = FindTokenLine( &rIStm, "#define", "_height" );
+ }
+ }
+ else
+ bStatus = sal_False;
+
+ if ( bStatus )
+ {
+ if ( ( nValue = (int) ParseDefine( aLine.getStr() ) ) > 0 )
+ {
+ nHeight = nValue;
+ aLine = FindTokenLine( &rIStm, "static", "_bits" );
+
+ if ( bStatus )
+ {
+ XBMFormat eFormat = XBM10;
+
+ if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("short")) != -1)
+ eFormat = XBM10;
+ else if (aLine.indexOfL(RTL_CONSTASCII_STRINGPARAM("char")) != -1)
+ eFormat = XBM11;
+ else
+ bStatus = sal_False;
+
+ if ( bStatus && nWidth && nHeight )
+ {
+ aBmp1 = Bitmap( Size( nWidth, nHeight ), 1 );
+ pAcc1 = aBmp1.AcquireWriteAccess();
+
+ if( pAcc1 )
+ {
+ aWhite = pAcc1->GetBestMatchingColor( Color( COL_WHITE ) );
+ aBlack = pAcc1->GetBestMatchingColor( Color( COL_BLACK ) );
+ bStatus = ParseData( &rIStm, aLine, eFormat );
+ }
+ else
+ bStatus = sal_False;
+ }
+ }
+ }
+ }
+ }
+
+ if( bStatus )
+ {
+ Bitmap aBlackBmp( Size( pAcc1->Width(), pAcc1->Height() ), 1 );
+
+ aBmp1.ReleaseAccess( pAcc1 ), pAcc1 = NULL;
+ aBlackBmp.Erase( Color( COL_BLACK ) );
+ rGraphic = BitmapEx( aBlackBmp, aBmp1 );
+ eReadState = XBMREAD_OK;
+ }
+ else
+ eReadState = XBMREAD_ERROR;
+ }
+ else
+ {
+ rIStm.ResetError();
+ eReadState = XBMREAD_NEED_MORE;
+ }
+
+ return eReadState;
+}
+
+// -------------
+// - ImportXBM -
+// -------------
+
+sal_Bool ImportXBM( SvStream& rStm, Graphic& rGraphic )
+{
+ XBMReader* pXBMReader = (XBMReader*) rGraphic.GetContext();
+ ReadState eReadState;
+ sal_Bool bRet = sal_True;
+
+ if( !pXBMReader )
+ pXBMReader = new XBMReader( rStm );
+
+ rGraphic.SetContext( NULL );
+ eReadState = pXBMReader->ReadXBM( rGraphic );
+
+ if( eReadState == XBMREAD_ERROR )
+ {
+ bRet = sal_False;
+ delete pXBMReader;
+ }
+ else if( eReadState == XBMREAD_OK )
+ delete pXBMReader;
+ else
+ rGraphic.SetContext( pXBMReader );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/ixbm/xbmread.hxx b/vcl/source/filter/ixbm/xbmread.hxx
new file mode 100644
index 000000000000..1b66f0956a76
--- /dev/null
+++ b/vcl/source/filter/ixbm/xbmread.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _XBMREAD_HXX
+#define _XBMREAD_HXX
+
+#include <vcl/graph.hxx>
+#include <vcl/bmpacc.hxx>
+
+#ifdef _XBMPRIVATE
+
+// ---------
+// - Enums -
+// ---------
+
+enum XBMFormat
+{
+ XBM10,
+ XBM11
+};
+
+enum ReadState
+{
+ XBMREAD_OK,
+ XBMREAD_ERROR,
+ XBMREAD_NEED_MORE
+};
+
+// -------------
+// - XBMReader -
+// -------------
+
+class XBMReader : public GraphicReader
+{
+ SvStream& rIStm;
+ Bitmap aBmp1;
+ BitmapWriteAccess* pAcc1;
+ short* pHexTable;
+ BitmapColor aWhite;
+ BitmapColor aBlack;
+ long nLastPos;
+ long nWidth;
+ long nHeight;
+ sal_Bool bStatus;
+
+ void InitTable();
+ rtl::OString FindTokenLine( SvStream* pInStm, const char* pTok1,
+ const char* pTok2 = NULL, const char* pTok3 = NULL );
+ long ParseDefine( const sal_Char* pDefine );
+ sal_Bool ParseData( SvStream* pInStm, const rtl::OString& aLastLine, XBMFormat eFormat );
+
+
+public:
+
+ XBMReader( SvStream& rStm );
+ virtual ~XBMReader();
+
+ ReadState ReadXBM( Graphic& rGraphic );
+};
+
+#endif // _XBMPRIVATE
+
+// -------------
+// - ImportXBM -
+// -------------
+
+sal_Bool ImportXBM( SvStream& rStream, Graphic& rGraphic );
+
+#endif // _XBMREAD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/ixpm/rgbtable.hxx b/vcl/source/filter/ixpm/rgbtable.hxx
new file mode 100644
index 000000000000..8f86fe8c371c
--- /dev/null
+++ b/vcl/source/filter/ixpm/rgbtable.hxx
@@ -0,0 +1,689 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+struct XPMRGBTab
+{
+ const char* name;
+ sal_uInt8 red;
+ sal_uInt8 green;
+ sal_uInt8 blue;
+};
+
+static XPMRGBTab pRGBTable[] = {
+{ "white", 255, 255, 255 },
+{ "black", 0, 0, 0 },
+{ "snow", 255, 250, 250 },
+{ "GhostWhite", 248, 248, 255 },
+{ "WhiteSmoke", 245, 245, 245 },
+{ "gainsboro", 220, 220, 220 },
+{ "FloralWhite", 255, 250, 240 },
+{ "OldLace", 253, 245, 230 },
+{ "linen", 250, 240, 230 },
+{ "AntiqueWhite", 250, 235, 215 },
+{ "PapayaWhip", 255, 239, 213 },
+{ "BlanchedAlmond", 255, 235, 205 },
+{ "bisque", 255, 228, 196 },
+{ "PeachPuff", 255, 218, 185 },
+{ "NavajoWhite", 255, 222, 173 },
+{ "moccasin", 255, 228, 181 },
+{ "cornsilk", 255, 248, 220 },
+{ "ivory", 255, 255, 240 },
+{ "LemonChiffon", 255, 250, 205 },
+{ "seashell", 255, 245, 238 },
+{ "honeydew", 240, 255, 240 },
+{ "MintCream", 245, 255, 250 },
+{ "azure", 240, 255, 255 },
+{ "AliceBlue", 240, 248, 255 },
+{ "lavender", 230, 230, 250 },
+{ "LavenderBlush", 255, 240, 245 },
+{ "MistyRose", 255, 228, 225 },
+{ "DarkSlateGray", 47, 79, 79 },
+{ "DarkSlateGrey", 47, 79, 79 },
+{ "DimGray", 105, 105, 105 },
+{ "DimGrey", 105, 105, 105 },
+{ "SlateGray", 112, 128, 144 },
+{ "SlateGrey", 112, 128, 144 },
+{ "LightSlateGray", 119, 136, 153 },
+{ "LightSlateGrey", 119, 136, 153 },
+{ "gray", 190, 190, 190 },
+{ "grey", 190, 190, 190 },
+{ "LightGrey", 211, 211, 211 },
+{ "LightGray", 211, 211, 211 },
+{ "MidnightBlue", 25, 25, 112 },
+{ "navy", 0, 0, 128 },
+{ "NavyBlue", 0, 0, 128 },
+{ "CornflowerBlue", 100, 149, 237 },
+{ "DarkSlateBlue", 72, 61, 139 },
+{ "SlateBlue", 106, 90, 205 },
+{ "MediumSlateBlue", 123, 104, 238 },
+{ "LightSlateBlue", 132, 112, 255 },
+{ "MediumBlue", 0, 0, 205 },
+{ "RoyalBlue", 65, 105, 225 },
+{ "blue", 0, 0, 255 },
+{ "DodgerBlue", 30, 144, 255 },
+{ "DeepSkyBlue", 0, 191, 255 },
+{ "SkyBlue", 135, 206, 235 },
+{ "LightSkyBlue", 135, 206, 250 },
+{ "SteelBlue", 70, 130, 180 },
+{ "LightSteelBlue", 176, 196, 222 },
+{ "LightBlue", 173, 216, 230 },
+{ "PowderBlue", 176, 224, 230 },
+{ "PaleTurquoise", 175, 238, 238 },
+{ "DarkTurquoise", 0, 206, 209 },
+{ "MediumTurquoise", 72, 209, 204 },
+{ "turquoise", 64, 224, 208 },
+{ "cyan", 0, 255, 255 },
+{ "LightCyan", 224, 255, 255 },
+{ "CadetBlue", 95, 158, 160 },
+{ "MediumAquamarine", 102, 205, 170 },
+{ "aquamarine", 127, 255, 212 },
+{ "DarkGreen", 0, 100, 0 },
+{ "DarkOliveGreen", 85, 107, 47 },
+{ "DarkSeaGreen", 143, 188, 143 },
+{ "SeaGreen", 46, 139, 87 },
+{ "MediumSeaGreen", 60, 179, 113 },
+{ "LightSeaGreen", 32, 178, 170 },
+{ "PaleGreen", 152, 251, 152 },
+{ "SpringGreen", 0, 255, 127 },
+{ "LawnGreen", 124, 252, 0 },
+{ "green", 0, 255, 0 },
+{ "chartreuse", 127, 255, 0 },
+{ "MediumSpringGreen", 0, 250, 154 },
+{ "GreenYellow", 173, 255 , 47 },
+{ "LimeGreen", 50, 205, 50 },
+{ "YellowGreen", 154, 205, 50 },
+{ "ForestGreen", 34, 139, 34 },
+{ "OliveDrab", 107, 142, 35 },
+{ "DarkKhaki", 189, 183, 107 },
+{ "khaki", 240, 230, 140 },
+{ "PaleGoldenrod", 238, 232, 170 },
+{ "LightGoldenrodYellow", 250, 250, 210 },
+{ "LightYellow", 255, 255, 224 },
+{ "yellow", 255, 255, 0 },
+{ "gold", 255, 215, 0 },
+{ "LightGoldenrod", 238, 221, 130 },
+{ "goldenrod", 218, 165, 32 },
+{ "DarkGoldenrod", 184, 134, 11 },
+{ "RosyBrown", 188, 143, 143 },
+{ "IndianRed", 205, 92, 92 },
+{ "SaddleBrown", 139, 69, 19 },
+{ "sienna", 160, 82, 45 },
+{ "peru", 205, 133, 63 },
+{ "burlywood", 222, 184, 135 },
+{ "beige", 245, 245, 220 },
+{ "wheat", 245, 222, 179 },
+{ "SandyBrown", 244, 164, 96 },
+{ "tan", 210, 180, 140 },
+{ "chocolate", 210, 105, 30 },
+{ "firebrick", 178, 34, 34 },
+{ "brown", 165, 42, 42 },
+{ "DarkSalmon", 233, 150, 122 },
+{ "salmon", 250, 128, 114 },
+{ "LightSalmon", 255, 160, 122 },
+{ "orange", 255, 165, 0 },
+{ "DarkOrange", 255, 140, 0 },
+{ "coral", 255, 127, 80 },
+{ "LightCoral", 240, 128, 128 },
+{ "tomato", 255, 99, 71 },
+{ "OrangeRed", 255, 69, 0 },
+{ "red", 255, 0, 0 },
+{ "HotPink", 255, 105, 180 },
+{ "DeepPink", 255, 20, 147 },
+{ "pink", 255, 192, 203 },
+{ "LightPink", 255, 182, 193 },
+{ "PaleVioletRed", 219, 112, 147 },
+{ "maroon", 176, 48, 96 },
+{ "MediumVioletRed", 199, 21, 133 },
+{ "VioletRed", 208, 32, 144 },
+{ "magenta", 255, 0, 255 },
+{ "violet", 238, 130, 238 },
+{ "plum", 221, 160, 221 },
+{ "orchid", 218, 112, 214 },
+{ "MediumOrchid", 186, 85, 211 },
+{ "DarkOrchid", 153, 50, 204 },
+{ "DarkViolet", 148, 0, 211 },
+{ "BlueViolet", 138, 43, 226 },
+{ "purple", 160, 32, 240 },
+{ "MediumPurple", 147, 112, 219 },
+{ "thistle", 216, 191, 216 },
+{ "snow1", 255, 250, 250 },
+{ "snow2", 238, 233, 233 },
+{ "snow3", 205, 201, 201 },
+{ "snow4", 139, 137, 137 },
+{ "seashell1", 255, 245, 238 },
+{ "seashell2", 238, 229, 222 },
+{ "seashell3", 205, 197, 191 },
+{ "seashell4", 139, 134, 130 },
+{ "AntiqueWhite1", 255, 239, 219 },
+{ "AntiqueWhite2", 238, 223, 204 },
+{ "AntiqueWhite3", 205, 192, 176 },
+{ "AntiqueWhite4", 139, 131, 120 },
+{ "bisque1", 255, 228, 196 },
+{ "bisque2", 238, 213, 183 },
+{ "bisque3", 205, 183, 158 },
+{ "bisque4", 139, 125, 107 },
+{ "PeachPuff1", 255, 218, 185 },
+{ "PeachPuff2", 238, 203, 173 },
+{ "PeachPuff3", 205, 175, 149 },
+{ "PeachPuff4", 139, 119, 101 },
+{ "NavajoWhite1", 255, 222, 173 },
+{ "NavajoWhite2", 238, 207, 161 },
+{ "NavajoWhite3", 205, 179, 139 },
+{ "NavajoWhite4", 139, 121, 94 },
+{ "LemonChiffon1", 255, 250, 205 },
+{ "LemonChiffon2", 238, 233, 191 },
+{ "LemonChiffon3", 205, 201, 165 },
+{ "LemonChiffon4", 139, 137, 112 },
+{ "cornsilk1", 255, 248, 220 },
+{ "cornsilk2", 238, 232, 205 },
+{ "cornsilk3", 205, 200, 177 },
+{ "cornsilk4", 139, 136, 120 },
+{ "ivory1", 255, 255, 240 },
+{ "ivory2", 238, 238, 224 },
+{ "ivory3", 205, 205, 193 },
+{ "ivory4", 139, 139, 131 },
+{ "honeydew1", 240, 255, 240 },
+{ "honeydew2", 224, 238, 224 },
+{ "honeydew3", 193, 205, 193 },
+{ "honeydew4", 131, 139, 131 },
+{ "LavenderBlush1", 255, 240, 245 },
+{ "LavenderBlush2", 238, 224, 229 },
+{ "LavenderBlush3", 205, 193, 197 },
+{ "LavenderBlush4", 139, 131, 134 },
+{ "MistyRose1", 255, 228, 225 },
+{ "MistyRose2", 238, 213, 210 },
+{ "MistyRose3", 205, 183, 181 },
+{ "MistyRose4", 139, 125, 123 },
+{ "azure1", 240, 255, 255 },
+{ "azure2", 224, 238, 238 },
+{ "azure3", 193, 205, 205 },
+{ "azure4", 131, 139, 139 },
+{ "SlateBlue1", 131, 111, 255 },
+{ "SlateBlue2", 122, 103, 238 },
+{ "SlateBlue3", 105, 89, 205 },
+{ "SlateBlue4", 71, 60, 139 },
+{ "RoyalBlue1", 72, 118, 255 },
+{ "RoyalBlue2", 67, 110, 238 },
+{ "RoyalBlue3", 58, 95, 205 },
+{ "RoyalBlue4", 39, 64, 139 },
+{ "blue1", 0, 0, 255 },
+{ "blue2", 0, 0, 238 },
+{ "blue3", 0, 0, 205 },
+{ "blue4", 0, 0, 139 },
+{ "DodgerBlue1", 30, 144, 255 },
+{ "DodgerBlue2", 28, 134, 238 },
+{ "DodgerBlue3", 24, 116, 205 },
+{ "DodgerBlue4", 16, 78, 139 },
+{ "SteelBlue1", 99, 184, 255 },
+{ "SteelBlue2", 92, 172, 238 },
+{ "SteelBlue3", 79, 148, 205 },
+{ "SteelBlue4", 54, 100, 139 },
+{ "DeepSkyBlue1", 0, 191, 255 },
+{ "DeepSkyBlue2", 0, 178, 238 },
+{ "DeepSkyBlue3", 0, 154, 205 },
+{ "DeepSkyBlue4", 0, 104, 139 },
+{ "SkyBlue1", 135, 206, 255 },
+{ "SkyBlue2", 126, 192, 238 },
+{ "SkyBlue3", 108, 166, 205 },
+{ "SkyBlue4", 74, 112, 139 },
+{ "LightSkyBlue1", 176, 226, 255 },
+{ "LightSkyBlue2", 164, 211, 238 },
+{ "LightSkyBlue3", 141, 182, 205 },
+{ "LightSkyBlue4", 96, 123, 139 },
+{ "SlateGray1", 198, 226, 255 },
+{ "SlateGray2", 185, 211, 238 },
+{ "SlateGray3", 159, 182, 205 },
+{ "SlateGray4", 108, 123, 139 },
+{ "LightSteelBlue1", 202, 225, 255 },
+{ "LightSteelBlue2", 188, 210, 238 },
+{ "LightSteelBlue3", 162, 181, 205 },
+{ "LightSteelBlue4", 110, 123, 139 },
+{ "LightBlue1", 191, 239, 255 },
+{ "LightBlue2", 178, 223, 238 },
+{ "LightBlue3", 154, 192, 205 },
+{ "LightBlue4", 104, 131, 139 },
+{ "LightCyan1", 224, 255, 255 },
+{ "LightCyan2", 209, 238, 238 },
+{ "LightCyan3", 180, 205, 205 },
+{ "LightCyan4", 122, 139, 139 },
+{ "PaleTurquoise1", 187, 255, 255 },
+{ "PaleTurquoise2", 174, 238, 238 },
+{ "PaleTurquoise3", 150, 205, 205 },
+{ "PaleTurquoise4", 102, 139, 139 },
+{ "CadetBlue1", 152, 245, 255 },
+{ "CadetBlue2", 142, 229, 238 },
+{ "CadetBlue3", 122, 197, 205 },
+{ "CadetBlue4", 83, 134, 139 },
+{ "turquoise1", 0, 245, 255 },
+{ "turquoise2", 0, 229, 238 },
+{ "turquoise3", 0, 197, 205 },
+{ "turquoise4", 0, 134, 139 },
+{ "cyan1", 0, 255, 255 },
+{ "cyan2", 0, 238, 238 },
+{ "cyan3", 0, 205, 205 },
+{ "cyan4", 0, 139, 139 },
+{ "DarkSlateGray1", 151, 255, 255 },
+{ "DarkSlateGray2", 141, 238, 238 },
+{ "DarkSlateGray3", 121, 205, 205 },
+{ "DarkSlateGray4", 82, 139, 139 },
+{ "aquamarine1", 127, 255, 212 },
+{ "aquamarine2", 118, 238, 198 },
+{ "aquamarine3", 102, 205, 170 },
+{ "aquamarine4", 69, 139, 116 },
+{ "DarkSeaGreen1", 193, 255, 193 },
+{ "DarkSeaGreen2", 180, 238, 180 },
+{ "DarkSeaGreen3", 155, 205, 155 },
+{ "DarkSeaGreen4", 105, 139, 105 },
+{ "SeaGreen1", 84, 255, 159 },
+{ "SeaGreen2", 78, 238, 148 },
+{ "SeaGreen3", 67, 205, 128 },
+{ "SeaGreen4", 46, 139, 87 },
+{ "PaleGreen1", 154, 255, 154 },
+{ "PaleGreen2", 144, 238, 144 },
+{ "PaleGreen3", 124, 205, 124 },
+{ "PaleGreen4", 84, 139, 84 },
+{ "SpringGreen1", 0, 255, 127 },
+{ "SpringGreen2", 0, 238, 118 },
+{ "SpringGreen3", 0, 205, 102 },
+{ "SpringGreen4", 0, 139, 69 },
+{ "green1", 0, 255, 0 },
+{ "green2", 0, 238, 0 },
+{ "green3", 0, 205, 0 },
+{ "green4", 0, 139, 0 },
+{ "chartreuse1", 127, 255, 0 },
+{ "chartreuse2", 118, 238, 0 },
+{ "chartreuse3", 102, 205, 0 },
+{ "chartreuse4", 69, 139, 0 },
+{ "OliveDrab1", 192, 255, 62 },
+{ "OliveDrab2", 179, 238, 58 },
+{ "OliveDrab3", 154, 205, 50 },
+{ "OliveDrab4", 105, 139, 34 },
+{ "DarkOliveGreen1", 202, 255, 112 },
+{ "DarkOliveGreen2", 188, 238, 104 },
+{ "DarkOliveGreen3", 162, 205, 90 },
+{ "DarkOliveGreen4", 110, 139, 61 },
+{ "khaki1", 255, 246, 143 },
+{ "khaki2", 238, 230, 133 },
+{ "khaki3", 205, 198, 115 },
+{ "khaki4", 139, 134, 78 },
+{ "LightGoldenrod1", 255, 236, 139 },
+{ "LightGoldenrod2", 238, 220, 130 },
+{ "LightGoldenrod3", 205, 190, 112 },
+{ "LightGoldenrod4", 139, 129, 76 },
+{ "LightYellow1", 255, 255, 224 },
+{ "LightYellow2", 238, 238, 209 },
+{ "LightYellow3", 205, 205, 180 },
+{ "LightYellow4", 139, 139, 122 },
+{ "yellow1", 255, 255, 0 },
+{ "yellow2", 238, 238, 0 },
+{ "yellow3", 205, 205, 0 },
+{ "yellow4", 139, 139, 0 },
+{ "gold1", 255, 215, 0 },
+{ "gold2", 238, 201, 0 },
+{ "gold3", 205, 173, 0 },
+{ "gold4", 139, 117, 0 },
+{ "goldenrod1", 255, 193, 37 },
+{ "goldenrod2", 238, 180, 34 },
+{ "goldenrod3", 205, 155, 29 },
+{ "goldenrod4", 139, 105, 20 },
+{ "DarkGoldenrod1", 255, 185, 15 },
+{ "DarkGoldenrod2", 238, 173, 14 },
+{ "DarkGoldenrod3", 205, 149, 12 },
+{ "DarkGoldenrod4", 139, 101, 8 },
+{ "RosyBrown1", 255, 193, 193 },
+{ "RosyBrown2", 238, 180, 180 },
+{ "RosyBrown3", 205, 155, 155 },
+{ "RosyBrown4", 139, 105, 105 },
+{ "IndianRed1", 255, 106, 106 },
+{ "IndianRed2", 238, 99, 99 },
+{ "IndianRed3", 205, 85, 85 },
+{ "IndianRed4", 139, 58, 58 },
+{ "sienna1", 255, 130, 71 },
+{ "sienna2", 238, 121, 66 },
+{ "sienna3", 205, 104, 57 },
+{ "sienna4", 139, 71, 38 },
+{ "burlywood1", 255, 211, 155 },
+{ "burlywood2", 238, 197, 145 },
+{ "burlywood3", 205, 170, 125 },
+{ "burlywood4", 139, 115, 85 },
+{ "wheat1", 255, 231, 186 },
+{ "wheat2", 238, 216, 174 },
+{ "wheat3", 205, 186, 150 },
+{ "wheat4", 139, 126, 102 },
+{ "tan1", 255, 165, 79 },
+{ "tan2", 238, 154, 73 },
+{ "tan3", 205, 133, 63 },
+{ "tan4", 139 , 90, 43 },
+{ "chocolate1", 255, 127, 36 },
+{ "chocolate2", 238, 118, 33 },
+{ "chocolate3", 205, 102, 29 },
+{ "chocolate4", 139, 69, 19 },
+{ "firebrick1", 255, 48, 48 },
+{ "firebrick2", 238, 44, 44 },
+{ "firebrick3", 205, 38, 38 },
+{ "firebrick4", 139, 26, 26 },
+{ "brown1", 255, 64, 64 },
+{ "brown2", 238, 59, 59 },
+{ "brown3", 205, 51, 51 },
+{ "brown4", 139, 35, 35 },
+{ "salmon1", 255, 140, 105 },
+{ "salmon2", 238, 130, 98 },
+{ "salmon3", 205, 112, 84 },
+{ "salmon4", 139, 76, 57 },
+{ "LightSalmon1", 255, 160, 122 },
+{ "LightSalmon2", 238, 149, 114 },
+{ "LightSalmon3", 205, 129, 98 },
+{ "LightSalmon4", 139, 87, 66 },
+{ "orange1", 255, 165, 0 },
+{ "orange2", 238, 154, 0 },
+{ "orange3", 205, 133, 0 },
+{ "orange4", 139 , 90, 0 },
+{ "DarkOrange1", 255, 127, 0 },
+{ "DarkOrange2", 238, 118, 0 },
+{ "DarkOrange3", 205, 102, 0 },
+{ "DarkOrange4", 139 , 69, 0 },
+{ "coral1", 255, 114, 86 },
+{ "coral2", 238, 106, 80 },
+{ "coral3", 205, 91, 69 },
+{ "coral4", 139, 62, 47 },
+{ "tomato1", 255, 99, 71 },
+{ "tomato2", 238, 92, 66 },
+{ "tomato3", 205, 79, 57 },
+{ "tomato4", 139, 54, 38 },
+{ "OrangeRed1", 255, 69, 0 },
+{ "OrangeRed2", 238, 64, 0 },
+{ "OrangeRed3", 205, 55, 0 },
+{ "OrangeRed4", 139, 37, 0 },
+{ "red1", 255, 0, 0 },
+{ "red2", 238, 0, 0 },
+{ "red3", 205, 0, 0 },
+{ "red4", 139, 0, 0 },
+{ "DeepPink1", 255, 20, 147 },
+{ "DeepPink2", 238, 18, 137 },
+{ "DeepPink3", 205, 16, 118 },
+{ "DeepPink4", 139, 10, 80 },
+{ "HotPink1", 255, 110, 180 },
+{ "HotPink2", 238, 106, 167 },
+{ "HotPink3", 205, 96, 144 },
+{ "HotPink4", 139, 58, 98 },
+{ "pink1", 255, 181, 197 },
+{ "pink2", 238, 169, 184 },
+{ "pink3", 205, 145, 158 },
+{ "pink4", 139, 99, 108 },
+{ "LightPink1", 255, 174, 185 },
+{ "LightPink2", 238, 162, 173 },
+{ "LightPink3", 205, 140, 149 },
+{ "LightPink4", 139, 95, 101 },
+{ "PaleVioletRed1", 255, 130, 171 },
+{ "PaleVioletRed2", 238, 121, 159 },
+{ "PaleVioletRed3", 205, 104, 137 },
+{ "PaleVioletRed4", 139, 71, 93 },
+{ "maroon1", 255, 52, 179 },
+{ "maroon2", 238, 48, 167 },
+{ "maroon3", 205, 41, 144 },
+{ "maroon4", 139, 28, 98 },
+{ "VioletRed1", 255, 62, 150 },
+{ "VioletRed2", 238, 58, 140 },
+{ "VioletRed3", 205, 50, 120 },
+{ "VioletRed4", 139, 34, 82 },
+{ "magenta1", 255, 0, 255 },
+{ "magenta2", 238, 0, 238 },
+{ "magenta3", 205, 0, 205 },
+{ "magenta4", 139, 0, 139 },
+{ "orchid1", 255, 131, 250 },
+{ "orchid2", 238, 122, 233 },
+{ "orchid3", 205, 105, 201 },
+{ "orchid4", 139, 71, 137 },
+{ "plum1", 255, 187, 255 },
+{ "plum2", 238, 174, 238 },
+{ "plum3", 205, 150, 205 },
+{ "plum4", 139, 102, 139 },
+{ "MediumOrchid1", 224, 102, 255 },
+{ "MediumOrchid2", 209, 95, 238 },
+{ "MediumOrchid3", 180, 82, 205 },
+{ "MediumOrchid4", 122, 55, 139 },
+{ "DarkOrchid1", 191, 62, 255 },
+{ "DarkOrchid2", 178, 58, 238 },
+{ "DarkOrchid3", 154, 50, 205 },
+{ "DarkOrchid4", 104, 34, 139 },
+{ "purple1", 155, 48, 255 },
+{ "purple2", 145, 44, 238 },
+{ "purple3", 125, 38, 205 },
+{ "purple4", 85, 26, 139 },
+{ "MediumPurple1", 171, 130, 255 },
+{ "MediumPurple2", 159, 121, 238 },
+{ "MediumPurple3", 137, 104, 205 },
+{ "MediumPurple4", 93, 71, 139 },
+{ "thistle1", 255, 225, 255 },
+{ "thistle2", 238, 210, 238 },
+{ "thistle3", 205, 181, 205 },
+{ "thistle4", 139, 123, 139 },
+{ "gray0", 0, 0, 0 },
+{ "grey0", 0, 0, 0 },
+{ "gray1", 3, 3, 3 },
+{ "grey1", 3, 3, 3 },
+{ "gray2", 5, 5, 5 },
+{ "grey2", 5, 5, 5 },
+{ "gray3", 8, 8, 8 },
+{ "grey3", 8, 8, 8 },
+{ "gray4", 10, 10, 10 },
+{ "grey4", 10, 10, 10 },
+{ "gray5", 13, 13, 13 },
+{ "grey5", 13, 13, 13 },
+{ "gray6", 15, 15, 15 },
+{ "grey6", 15, 15, 15 },
+{ "gray7", 18, 18, 18 },
+{ "grey7", 18, 18, 18 },
+{ "gray8", 20, 20, 20 },
+{ "grey8", 20, 20, 20 },
+{ "gray9", 23, 23, 23 },
+{ "grey9", 23, 23, 23 },
+{ "gray10", 26, 26, 26 },
+{ "grey10", 26, 26, 26 },
+{ "gray11", 28, 28, 28 },
+{ "grey11", 28, 28, 28 },
+{ "gray12", 31, 31, 31 },
+{ "grey12", 31, 31, 31 },
+{ "gray13", 33, 33, 33 },
+{ "grey13", 33, 33, 33 },
+{ "gray14", 36, 36, 36 },
+{ "grey14", 36, 36, 36 },
+{ "gray15", 38, 38, 38 },
+{ "grey15", 38, 38, 38 },
+{ "gray16", 41, 41, 41 },
+{ "grey16", 41, 41, 41 },
+{ "gray17", 43, 43, 43 },
+{ "grey17", 43, 43, 43 },
+{ "gray18", 46, 46, 46 },
+{ "grey18", 46, 46, 46 },
+{ "gray19", 48, 48, 48 },
+{ "grey19", 48, 48, 48 },
+{ "gray20", 51, 51, 51 },
+{ "grey20", 51, 51, 51 },
+{ "gray21", 54, 54, 54 },
+{ "grey21", 54, 54, 54 },
+{ "gray22", 56, 56, 56 },
+{ "grey22", 56, 56, 56 },
+{ "gray23", 59, 59, 59 },
+{ "grey23", 59, 59, 59 },
+{ "gray24", 61, 61, 61 },
+{ "grey24", 61, 61, 61 },
+{ "gray25", 64, 64, 64 },
+{ "grey25", 64, 64, 64 },
+{ "gray26", 66, 66, 66 },
+{ "grey26", 66, 66, 66 },
+{ "gray27", 69, 69, 69 },
+{ "grey27", 69, 69, 69 },
+{ "gray28", 71, 71, 71 },
+{ "grey28", 71, 71, 71 },
+{ "gray29", 74, 74, 74 },
+{ "grey29", 74, 74, 74 },
+{ "gray30", 77, 77, 77 },
+{ "grey30", 77, 77, 77 },
+{ "gray31", 79, 79, 79 },
+{ "grey31", 79, 79, 79 },
+{ "gray32", 82, 82, 82 },
+{ "grey32", 82, 82, 82 },
+{ "gray33", 84, 84, 84 },
+{ "grey33", 84, 84, 84 },
+{ "gray34", 87, 87, 87 },
+{ "grey34", 87, 87, 87 },
+{ "gray35", 89, 89, 89 },
+{ "grey35", 89, 89, 89 },
+{ "gray36", 92, 92, 92 },
+{ "grey36", 92, 92, 92 },
+{ "gray37", 94, 94, 94 },
+{ "grey37", 94, 94, 94 },
+{ "gray38", 97, 97, 97 },
+{ "grey38", 97, 97, 97 },
+{ "gray39", 99, 99, 99 },
+{ "grey39", 99, 99, 99 },
+{ "gray40", 102, 102, 102 },
+{ "grey40", 102, 102, 102 },
+{ "gray41", 105, 105, 105 },
+{ "grey41", 105, 105, 105 },
+{ "gray42", 107, 107, 107 },
+{ "grey42", 107, 107, 107 },
+{ "gray43", 110, 110, 110 },
+{ "grey43", 110, 110, 110 },
+{ "gray44", 112, 112, 112 },
+{ "grey44", 112, 112, 112 },
+{ "gray45", 115, 115, 115 },
+{ "grey45", 115, 115, 115 },
+{ "gray46", 117, 117, 117 },
+{ "grey46", 117, 117, 117 },
+{ "gray47", 120, 120, 120 },
+{ "grey47", 120, 120, 120 },
+{ "gray48", 122, 122, 122 },
+{ "grey48", 122, 122, 122 },
+{ "gray49", 125, 125, 125 },
+{ "grey49", 125, 125, 125 },
+{ "gray50", 127, 127, 127 },
+{ "grey50", 127, 127, 127 },
+{ "gray51", 130, 130, 130 },
+{ "grey51", 130, 130, 130 },
+{ "gray52", 133, 133, 133 },
+{ "grey52", 133, 133, 133 },
+{ "gray53", 135, 135, 135 },
+{ "grey53", 135, 135, 135 },
+{ "gray54", 138, 138, 138 },
+{ "grey54", 138, 138, 138 },
+{ "gray55", 140, 140, 140 },
+{ "grey55", 140, 140, 140 },
+{ "gray56", 143, 143, 143 },
+{ "grey56", 143, 143, 143 },
+{ "gray57", 145, 145, 145 },
+{ "grey57", 145, 145, 145 },
+{ "gray58", 148, 148, 148 },
+{ "grey58", 148, 148, 148 },
+{ "gray59", 150, 150, 150 },
+{ "grey59", 150, 150, 150 },
+{ "gray60", 153, 153, 153 },
+{ "grey60", 153, 153, 153 },
+{ "gray61", 156, 156, 156 },
+{ "grey61", 156, 156, 156 },
+{ "gray62", 158, 158, 158 },
+{ "grey62", 158, 158, 158 },
+{ "gray63", 161, 161, 161 },
+{ "grey63", 161, 161, 161 },
+{ "gray64", 163, 163, 163 },
+{ "grey64", 163, 163, 163 },
+{ "gray65", 166, 166, 166 },
+{ "grey65", 166, 166, 166 },
+{ "gray66", 168, 168, 168 },
+{ "grey66", 168, 168, 168 },
+{ "gray67", 171, 171, 171 },
+{ "grey67", 171, 171, 171 },
+{ "gray68", 173, 173, 173 },
+{ "grey68", 173, 173, 173 },
+{ "gray69", 176, 176, 176 },
+{ "grey69", 176, 176, 176 },
+{ "gray70", 179, 179, 179 },
+{ "grey70", 179, 179, 179 },
+{ "gray71", 181, 181, 181 },
+{ "grey71", 181, 181, 181 },
+{ "gray72", 184, 184, 184 },
+{ "grey72", 184, 184, 184 },
+{ "gray73", 186, 186, 186 },
+{ "grey73", 186, 186, 186 },
+{ "gray74", 189, 189, 189 },
+{ "grey74", 189, 189, 189 },
+{ "gray75", 191, 191, 191 },
+{ "grey75", 191, 191, 191 },
+{ "gray76", 194, 194, 194 },
+{ "grey76", 194, 194, 194 },
+{ "gray77", 196, 196, 196 },
+{ "grey77", 196, 196, 196 },
+{ "gray78", 199, 199, 199 },
+{ "grey78", 199, 199, 199 },
+{ "gray79", 201, 201, 201 },
+{ "grey79", 201, 201, 201 },
+{ "gray80", 204, 204, 204 },
+{ "grey80", 204, 204, 204 },
+{ "gray81", 207, 207, 207 },
+{ "grey81", 207, 207, 207 },
+{ "gray82", 209, 209, 209 },
+{ "grey82", 209, 209, 209 },
+{ "gray83", 212, 212, 212 },
+{ "grey83", 212, 212, 212 },
+{ "gray84", 214, 214, 214 },
+{ "grey84", 214, 214, 214 },
+{ "gray85", 217, 217, 217 },
+{ "grey85", 217, 217, 217 },
+{ "gray86", 219, 219, 219 },
+{ "grey86", 219, 219, 219 },
+{ "gray87", 222, 222, 222 },
+{ "grey87", 222, 222, 222 },
+{ "gray88", 224, 224, 224 },
+{ "grey88", 224, 224, 224 },
+{ "gray89", 227, 227, 227 },
+{ "grey89", 227, 227, 227 },
+{ "gray90", 229, 229, 229 },
+{ "grey90", 229, 229, 229 },
+{ "gray91", 232, 232, 232 },
+{ "grey91", 232, 232, 232 },
+{ "gray92", 235, 235, 235 },
+{ "grey92", 235, 235, 235 },
+{ "gray93", 237, 237, 237 },
+{ "grey93", 237, 237, 237 },
+{ "gray94", 240, 240, 240 },
+{ "grey94", 240, 240, 240 },
+{ "gray95", 242, 242, 242 },
+{ "grey95", 242, 242, 242 },
+{ "gray96", 245, 245, 245 },
+{ "grey96", 245, 245, 245 },
+{ "gray97", 247, 247, 247 },
+{ "grey97", 247, 247, 247 },
+{ "gray98", 250, 250, 250 },
+{ "grey98", 250, 250, 250 },
+{ "gray99", 252, 252, 252 },
+{ "grey99", 252, 252, 252 },
+{ "gray100", 255, 255, 255 },
+{ "grey100", 255, 255, 255 },
+{ "DarkGrey", 169, 169, 169 },
+{ "DarkGray", 169, 169, 169 },
+{ "DarkBlue", 0, 0, 139 },
+{ "DarkCyan", 0, 139, 139 },
+{ "DarkMagenta", 139, 0, 139 },
+{ "DarkRed", 139, 0, 0 },
+{ "LightGreen", 144, 238, 144 },
+{ NULL, 0 , 0, 0}
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/ixpm/xpmread.cxx b/vcl/source/filter/ixpm/xpmread.cxx
new file mode 100644
index 000000000000..e15bf33c1bcd
--- /dev/null
+++ b/vcl/source/filter/ixpm/xpmread.cxx
@@ -0,0 +1,690 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <vcl/bmpacc.hxx>
+#include <vcl/graph.hxx>
+#include "rgbtable.hxx"
+#define _XPMPRIVATE
+#include "xpmread.hxx"
+
+// -------------
+// - XPMReader -
+// -------------
+
+XPMReader::XPMReader( SvStream& rStm ) :
+ mrIStm ( rStm ),
+ mpAcc ( NULL ),
+ mpMaskAcc ( NULL ),
+ mnLastPos ( rStm.Tell() ),
+ mnWidth ( 0 ),
+ mnHeight ( 0 ),
+ mnColors ( 0 ),
+ mnCpp ( 0 ),
+ mbTransparent ( sal_False ),
+ mbStatus ( sal_True ),
+ mnStatus ( 0 ),
+ mnIdentifier ( XPMIDENTIFIER ),
+ mcThisByte ( 0 ),
+ mnTempAvail ( 0 ),
+ mpFastColorTable( NULL ),
+ mpColMap ( NULL )
+{
+
+}
+
+// ------------------------------------------------------------------------
+
+XPMReader::~XPMReader()
+{
+ if( mpAcc )
+ maBmp.ReleaseAccess( mpAcc );
+}
+
+// ------------------------------------------------------------------------
+
+#ifdef _MSC_VER
+#pragma optimize ("",off)
+#endif
+
+ReadState XPMReader::ReadXPM( Graphic& rGraphic )
+{
+ ReadState eReadState;
+ sal_uInt8 cDummy;
+
+ // sehen, ob wir _alles_ lesen koennen
+ mrIStm.Seek( STREAM_SEEK_TO_END );
+ mrIStm >> cDummy;
+
+ // falls wir nicht alles lesen koennen
+ // kehren wir zurueck und warten auf neue Daten
+ if ( mrIStm.GetError() != ERRCODE_IO_PENDING )
+ {
+ mrIStm.Seek( mnLastPos );
+ mbStatus = sal_True;
+
+ if ( mbStatus )
+ {
+ mpStringBuf = new sal_uInt8 [ XPMSTRINGBUF ];
+ mpTempBuf = new sal_uInt8 [ XPMTEMPBUFSIZE ];
+
+ if ( ( mbStatus = ImplGetString() ) == sal_True )
+ {
+ mnIdentifier = XPMVALUES; // Bitmap informationen einholen
+ mnWidth = ImplGetULONG( 0 );
+ mnHeight = ImplGetULONG( 1 );
+ mnColors = ImplGetULONG( 2 );
+ mnCpp = ImplGetULONG( 3 );
+ }
+ if ( mnColors > ( SAL_MAX_UINT32 / ( 4 + mnCpp ) ) )
+ mbStatus = sal_False;
+ if ( ( mnWidth * mnCpp ) >= XPMSTRINGBUF )
+ mbStatus = sal_False;
+ if ( mbStatus && mnWidth && mnHeight && mnColors && mnCpp )
+ {
+ mnIdentifier = XPMCOLORS;
+
+ // mpColMap beinhaltet fuer jede vorhandene
+ // Farbe: ( mnCpp )Byte(s)-> ASCII Eintrag der der Farbe zugeordnet ist
+ // 1 Byte -> 0xff wenn Farbe transparent ist
+ // 3 Bytes -> RGB Wert der Farbe
+ mpColMap = new sal_uInt8[ mnColors * ( 4 + mnCpp ) ];
+ if ( mpColMap )
+ {
+ for ( sal_uLong i = 0; i < mnColors; i++ )
+ {
+ if ( ImplGetColor( i ) == sal_False )
+ {
+ mbStatus = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ mbStatus = sal_False;
+
+ if ( mbStatus )
+ {
+ // bei mehr als 256 Farben wird eine 24 Bit Grafik erstellt
+ sal_uInt16 nBits = 1;
+ if ( mnColors > 256 )
+ nBits = 24;
+ else if ( mnColors > 16 )
+ nBits = 8;
+ else if ( mnColors > 2 )
+ nBits = 4;
+ else
+ nBits = 1;
+
+ maBmp = Bitmap( Size( mnWidth, mnHeight ), nBits );
+ mpAcc = maBmp.AcquireWriteAccess();
+
+ // mbTransparent ist sal_True wenn mindestens eine Farbe Transparent ist
+ if ( mbTransparent )
+ {
+ maMaskBmp = Bitmap( Size( mnWidth, mnHeight ), 1 );
+ if ( ( mpMaskAcc = maMaskBmp.AcquireWriteAccess() ) == NULL )
+ mbStatus = sal_False;
+ }
+ if( mpAcc && mbStatus )
+ {
+ sal_uLong i;
+ if ( mnColors <=256 ) // palette is only needed by using less than 257
+ { // colors
+
+ sal_uInt8* pPtr = &mpColMap[mnCpp];
+
+ for ( i = 0; i < mnColors; i++ )
+ {
+ mpAcc->SetPaletteColor( (sal_uInt8)i, Color( pPtr[1], pPtr[2], pPtr[3] ) );
+ pPtr += ( mnCpp + 4 );
+ }
+ // using 2 charakters per pixel and less than 257 Colors we speed up
+ if ( mnCpp == 2 ) // by using a 64kb indexing table
+ {
+ mpFastColorTable = new sal_uInt8[ 256 * 256 ];
+ for ( pPtr = mpColMap, i = 0; i < mnColors; i++, pPtr += mnCpp + 4 )
+ {
+ sal_uLong j = pPtr[ 0 ] << 8;
+ j += pPtr[ 1 ];
+ mpFastColorTable[ j ] = (sal_uInt8)i;
+ }
+ }
+ }
+ // now we get the bitmap data
+ mnIdentifier = XPMPIXELS;
+ for ( i = 0; i < mnHeight; i++ )
+ {
+ if ( ImplGetScanLine( i ) == sal_False )
+ {
+ mbStatus = sal_False;
+ break;
+ }
+ }
+ mnIdentifier = XPMEXTENSIONS;
+ }
+ }
+ }
+
+ delete[] mpFastColorTable;
+ delete[] mpColMap;
+ delete[] mpStringBuf;
+ delete[] mpTempBuf;
+
+ }
+ if( mbStatus )
+ {
+ if ( mpMaskAcc )
+ {
+ maMaskBmp.ReleaseAccess ( mpMaskAcc), mpMaskAcc = NULL;
+ maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
+ rGraphic = Graphic( BitmapEx( maBmp, maMaskBmp ) );
+ }
+ else
+ {
+ maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
+ rGraphic = maBmp;
+ }
+ eReadState = XPMREAD_OK;
+ }
+ else
+ {
+ if ( mpMaskAcc ) maMaskBmp.ReleaseAccess ( mpMaskAcc), mpMaskAcc = NULL;
+ if ( mpAcc ) maBmp.ReleaseAccess( mpAcc ), mpAcc = NULL;
+ eReadState = XPMREAD_ERROR;
+ }
+ }
+ else
+ {
+ mrIStm.ResetError();
+ eReadState = XPMREAD_NEED_MORE;
+ }
+ return eReadState;
+}
+
+#ifdef _MSC_VER
+#pragma optimize ("",on)
+#endif
+
+// ------------------------------------------------------------------------
+// ImplGetColor ermittelt saemtliche Farbwerte,
+// die Rueckgabe ist sal_True wenn saemtliche Farben zugeordnet werden konnten
+
+sal_Bool XPMReader::ImplGetColor( sal_uLong nNumb )
+{
+ sal_uInt8* pString = mpStringBuf;
+ sal_uInt8* pPtr = ( mpColMap + nNumb * ( 4 + mnCpp ) );
+ sal_Bool bStatus = ImplGetString();
+
+ if ( bStatus )
+ {
+ for ( sal_uLong i = 0; i < mnCpp; i++ )
+ *pPtr++ = *pString++;
+ bStatus = ImplGetColSub ( pPtr );
+ }
+ return bStatus;
+}
+
+// ------------------------------------------------------------------------
+// ImpGetScanLine liest den String mpBufSize aus und schreibt die Pixel in die
+// Bitmap. Der Parameter nY gibt die horizontale Position an.
+
+sal_Bool XPMReader::ImplGetScanLine( sal_uLong nY )
+{
+ sal_Bool bStatus = ImplGetString();
+ sal_uInt8* pString = mpStringBuf;
+ sal_uInt8* pColor;
+ BitmapColor aWhite;
+ BitmapColor aBlack;
+
+ if ( bStatus )
+ {
+ if ( mpMaskAcc )
+ {
+ aWhite = mpMaskAcc->GetBestMatchingColor( Color( COL_WHITE ) );
+ aBlack = mpMaskAcc->GetBestMatchingColor( Color( COL_BLACK ) );
+ }
+ if ( mnStringSize != ( mnWidth * mnCpp ))
+ bStatus = sal_False;
+ else
+ {
+ sal_uLong i, j;
+ if ( mpFastColorTable )
+ {
+ for ( i = 0; i < mnWidth; i++ )
+ {
+ j = (*pString++) << 8;
+ j += *pString++;
+ sal_uInt8 k = (sal_uInt8)mpFastColorTable[ j ];
+ mpAcc->SetPixel( nY, i, BitmapColor( (sal_uInt8)k ) );
+
+ if ( mpMaskAcc )
+ mpMaskAcc->SetPixel( nY, i,
+ ( mpColMap[ k * (mnCpp + 4) + mnCpp] ) ? aWhite : aBlack );
+ }
+ }
+ else for ( i = 0; i < mnWidth; i++ )
+ {
+ pColor = mpColMap;
+ for ( j = 0; j < mnColors; j++ )
+ {
+ if ( ImplCompare( pString, pColor, mnCpp, XPMCASESENSITIVE ) == sal_True )
+ {
+ if ( mnColors > 256 )
+ mpAcc->SetPixel( nY, i, Color ( pColor[3], pColor[4], pColor[5] ) );
+ else
+ mpAcc->SetPixel( nY, i, BitmapColor( (sal_uInt8) j ) );
+
+ if ( mpMaskAcc )
+ mpMaskAcc->SetPixel( nY, i, (
+ pColor[ mnCpp ] ) ? aWhite : aBlack );
+
+ break;
+ }
+ pColor += ( mnCpp + 4 );
+ }
+ pString += mnCpp;
+ }
+
+ }
+ }
+ return bStatus;
+}
+
+// ------------------------------------------------------------------------
+// versucht aus mpStringBuf einen Farbwert zu uebermitteln
+// wurde eine Farbe gefunden wird an pDest[1]..pDest[2] der RGB wert geschrieben
+// pDest[0] enthaelt 0xff wenn die Farbe transparent ist sonst 0
+
+sal_Bool XPMReader::ImplGetColSub( sal_uInt8* pDest )
+{
+ unsigned char cTransparent[] = "None";
+
+ sal_Bool bColStatus = sal_False;
+
+ if ( ImplGetColKey( 'c' ) || ImplGetColKey( 'm' ) || ImplGetColKey( 'g' ) )
+ {
+ // hexentry for RGB or HSV color ?
+ if ( *mpPara == '#' )
+ {
+ *pDest++ = 0;
+ bColStatus = sal_True;
+ switch ( mnParaSize )
+ {
+ case 25 :
+ ImplGetRGBHex ( pDest, 6 );
+ break;
+ case 13 :
+ ImplGetRGBHex ( pDest, 2 );
+ break;
+ case 7 :
+ ImplGetRGBHex ( pDest, 0 );
+ break;
+ default:
+ bColStatus = sal_False;
+ break;
+ }
+ }
+ // maybe pixel is transparent
+ else if ( ImplCompare( &cTransparent[0], mpPara, 4 ))
+ {
+ *pDest++ = 0xff;
+ bColStatus = sal_True;
+ mbTransparent = sal_True;
+ }
+ // last we will try to get the colorname
+ else if ( mnParaSize > 2 ) // name must enlarge the minimum size
+ {
+ sal_uLong i = 0;
+ while ( sal_True )
+ {
+ if ( pRGBTable[ i ].name == NULL )
+ break;
+ if ( pRGBTable[ i ].name[ mnParaSize ] == 0 )
+ {
+ if ( ImplCompare ( (unsigned char*)pRGBTable[ i ].name,
+ mpPara, mnParaSize, XPMCASENONSENSITIVE ) )
+ {
+ bColStatus = sal_True;
+ *pDest++ = 0;
+ *pDest++ = pRGBTable[ i ].red;
+ *pDest++ = pRGBTable[ i ].green;
+ *pDest++ = pRGBTable[ i ].blue;
+ }
+ }
+ i++;
+ }
+ }
+ }
+ return bColStatus;
+}
+
+// ------------------------------------------------------------------------
+// ImplGetColKey durchsuch den String mpStringBuf nach einem Parameter 'nKey'
+// und gibt einen sal_Bool zurueck. ( wenn sal_True werden mpPara und mnParaSize gesetzt )
+
+sal_Bool XPMReader::ImplGetColKey( sal_uInt8 nKey )
+{
+ sal_uInt8 nTemp, nPrev = ' ';
+
+ mpPara = mpStringBuf + mnCpp + 1;
+ mnParaSize = 0;
+
+ while ( *mpPara != 0 )
+ {
+ if ( *mpPara == nKey )
+ {
+ nTemp = *( mpPara + 1 );
+ if ( nTemp == ' ' || nTemp == 0x09 )
+ {
+ if ( nPrev == ' ' || nPrev == 0x09 )
+ break;
+ }
+ }
+ nPrev = *mpPara;
+ mpPara++;
+ }
+ if ( *mpPara )
+ {
+ mpPara++;
+ while ( (*mpPara == ' ') || (*mpPara == 0x09) )
+ {
+ mpPara++;
+ }
+ if ( *mpPara != 0 )
+ {
+ while ( *(mpPara+mnParaSize) != ' ' && *(mpPara+mnParaSize) != 0x09 &&
+ *(mpPara+mnParaSize) != 0 )
+ {
+ mnParaSize++;
+ }
+ }
+ }
+ return ( mnParaSize ) ? sal_True : sal_False;
+}
+
+// ------------------------------------------------------------------------
+// ImplGetRGBHex uebersetzt den ASCII-Hexadezimalwert der sich bei mpPara befindet
+// in einen RGB wert und schreibt diesen nach pDest
+// folgende Formate muessen sich bei mpPara befinden:
+// wenn nAdd = 0 : '#12ab12' -> RGB = 0x12, 0xab, 0x12
+// 2 : '#1234abcd1234' " " " "
+// 6 : '#12345678abcdefab12345678' " " " "
+
+
+void XPMReader::ImplGetRGBHex( sal_uInt8* pDest,sal_uLong nAdd )
+{
+ sal_uInt8* pPtr = mpPara+1;
+ sal_uInt8 nHex, nTemp;
+
+ for ( sal_uLong i = 0; i < 3; i++ )
+ {
+ nHex = (*pPtr++) - '0';
+ if ( nHex > 9 )
+ nHex = ((nHex - 'A' + '0') & 7) + 10;
+
+ nTemp = (*pPtr++) - '0';
+ if ( nTemp > 9 )
+ nTemp = ((nTemp - 'A' + '0') & 7) + 10;
+ nHex = ( nHex << 4 ) + nTemp;
+
+ pPtr += nAdd;
+ *pDest++ = (sal_uInt8)nHex;
+ }
+}
+
+// ------------------------------------------------------------------------
+// ImplGetUlong gibt den wert einer bis zu 6stelligen ASCII-Dezimalzahl zurueck.
+
+sal_uLong XPMReader::ImplGetULONG( sal_uLong nPara )
+{
+ if ( ImplGetPara ( nPara ) )
+ {
+ sal_uLong nRetValue = 0;
+ sal_uInt8* pPtr = mpPara;
+
+ if ( ( mnParaSize > 6 ) || ( mnParaSize == 0 ) ) return 0;
+ for ( sal_uLong i = 0; i < mnParaSize; i++ )
+ {
+ sal_uInt8 j = (*pPtr++) - 48;
+ if ( j > 9 ) return 0; // ascii is invalid
+ nRetValue*=10;
+ nRetValue+=j;
+ }
+ return nRetValue;
+ }
+ else return 0;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool XPMReader::ImplCompare( sal_uInt8* pSource, sal_uInt8* pDest, sal_uLong nSize, sal_uLong nMode )
+{
+ sal_Bool bRet = sal_True;
+
+ if ( nMode == XPMCASENONSENSITIVE )
+ {
+ for ( sal_uLong i = 0; i < nSize; i++ )
+ {
+ if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for ( sal_uLong i = 0; i < nSize; i++ )
+ {
+ if ( pSource[i] != pDest[i] )
+ {
+ bRet = sal_False;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+// ------------------------------------------------------------------------
+// ImplGetPara versucht den nNumb ( 0...x ) Parameter aus mpStringBuf zu ermitteln.
+// Ein Parameter ist durch Spaces oder Tabs von den anderen getrennt.
+// Konnte der Parameter gefunden werden ist der Rueckgabewert sal_True und mpPara + mnParaSize
+// werden gesetzt.
+
+sal_Bool XPMReader::ImplGetPara ( sal_uLong nNumb )
+{
+ sal_uInt8 nByte;
+ sal_uLong pSize = 0;
+ sal_uInt8* pPtr = mpStringBuf;
+ sal_uLong nCount = 0;
+
+ if ( ( *pPtr != ' ' ) && ( *pPtr != 0x09 ) )
+ {
+ mpPara = pPtr;
+ mnParaSize = 0;
+ nCount = 0;
+ }
+ else
+ {
+ mpPara = NULL;
+ nCount = 0xffffffff;
+ }
+
+ while ( pSize < mnStringSize )
+ {
+ nByte = *pPtr;
+
+ if ( mpPara )
+ {
+ if ( ( nByte == ' ' ) || ( nByte == 0x09 ) )
+ {
+ if ( nCount == nNumb )
+ break;
+ else
+ mpPara = NULL;
+ }
+ else
+ mnParaSize++;
+ }
+ else
+ {
+ if ( ( nByte != ' ' ) && ( nByte != 0x09 ) )
+ {
+ mpPara = pPtr;
+ mnParaSize = 1;
+ nCount++;
+ }
+ }
+ pSize++;
+ pPtr++;
+ }
+ return ( ( nCount == nNumb ) && ( mpPara ) ) ? sal_True : sal_False;
+}
+
+// ------------------------------------------------------------------------
+// Der naechste String wird ausgelesen und in mpStringBuf (mit 0 abgeschlossen) abgelegt;
+// mnStringSize enthaelt die Groesse des gelesenen Strings.
+// Bemerkungen wie '//' und '/*.....*/' werden uebersprungen.
+
+sal_Bool XPMReader::ImplGetString( void )
+{
+ sal_uInt8 sID[] = "/* XPM */";
+ sal_uInt8* pString = mpStringBuf;
+
+ mnStringSize = 0;
+ mpStringBuf[0] = 0;
+
+ while( mbStatus && ( mnStatus != XPMFINISHED ) )
+ {
+ if ( mnTempAvail == 0 )
+ {
+ mnTempAvail = mrIStm.Read( mpTempBuf, XPMTEMPBUFSIZE );
+ if ( mnTempAvail == 0 )
+ break;
+
+ mpTempPtr = mpTempBuf;
+
+ if ( mnIdentifier == XPMIDENTIFIER )
+ {
+ if ( mnTempAvail <= 50 )
+ {
+ mbStatus = sal_False; // file is too short to be a correct XPM format
+ break;
+ }
+ for ( int i = 0; i < 9; i++ ) // searching for "/* XPM */"
+ if ( *mpTempPtr++ != sID[i] )
+ {
+ mbStatus = sal_False;
+ break;
+ }
+ mnTempAvail-=9;
+ mnIdentifier++;
+ }
+ }
+ mcLastByte = mcThisByte;
+ mcThisByte = *mpTempPtr++;
+ mnTempAvail--;
+
+ if ( mnStatus & XPMDOUBLE )
+ {
+ if ( mcThisByte == 0x0a )
+ mnStatus &=~XPMDOUBLE;
+ continue;
+ }
+ if ( mnStatus & XPMREMARK )
+ {
+ if ( ( mcThisByte == '/' ) && ( mcLastByte == '*' ) )
+ mnStatus &=~XPMREMARK;
+ continue;
+ }
+ if ( mnStatus & XPMSTRING ) // characters in string
+ {
+ if ( mcThisByte == '"' )
+ {
+ mnStatus &=~XPMSTRING; // end of parameter by eol
+ break;
+ }
+ if ( mnStringSize >= ( XPMSTRINGBUF - 1 ) )
+ {
+ mbStatus = sal_False;
+ break;
+ }
+ *pString++ = mcThisByte;
+ pString[0] = 0;
+ mnStringSize++;
+ continue;
+ }
+ else
+ { // characters beside string
+ switch ( mcThisByte )
+ {
+ case '*' :
+ if ( mcLastByte == '/' ) mnStatus |= XPMREMARK;
+ break;
+ case '/' :
+ if ( mcLastByte == '/' ) mnStatus |= XPMDOUBLE;
+ break;
+ case '"' : mnStatus |= XPMSTRING;
+ break;
+ case '{' :
+ if ( mnIdentifier == XPMDEFINITION )
+ mnIdentifier++;
+ break;
+ case '}' :
+ if ( mnIdentifier == XPMENDEXT )
+ mnStatus = XPMFINISHED;
+ break;
+ }
+ }
+ }
+ return mbStatus;
+}
+
+// -------------
+// - ImportXPM -
+// -------------
+
+sal_Bool ImportXPM( SvStream& rStm, Graphic& rGraphic )
+{
+ XPMReader* pXPMReader = (XPMReader*) rGraphic.GetContext();
+ ReadState eReadState;
+ sal_Bool bRet = sal_True;
+
+ if( !pXPMReader )
+ pXPMReader = new XPMReader( rStm );
+
+ rGraphic.SetContext( NULL );
+ eReadState = pXPMReader->ReadXPM( rGraphic );
+
+ if( eReadState == XPMREAD_ERROR )
+ {
+ bRet = sal_False;
+ delete pXPMReader;
+ }
+ else if( eReadState == XPMREAD_OK )
+ delete pXPMReader;
+ else
+ rGraphic.SetContext( pXPMReader );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/ixpm/xpmread.hxx b/vcl/source/filter/ixpm/xpmread.hxx
new file mode 100644
index 000000000000..79abfe88e74c
--- /dev/null
+++ b/vcl/source/filter/ixpm/xpmread.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _XPMREAD_HXX
+#define _XPMREAD_HXX
+
+#include <vcl/bitmap.hxx>
+
+#ifdef _XPMPRIVATE
+
+#define XPMTEMPBUFSIZE 0x00008000
+#define XPMSTRINGBUF 0x00008000
+
+#define XPMIDENTIFIER 0x00000001 // mnIdentifier includes on of the six phases
+#define XPMDEFINITION 0x00000002 // the XPM format consists of
+#define XPMVALUES 0x00000003
+#define XPMCOLORS 0x00000004
+#define XPMPIXELS 0x00000005
+#define XPMEXTENSIONS 0x00000006
+#define XPMENDEXT 0x00000007
+
+
+#define XPMREMARK 0x00000001 // defines used by mnStatus
+#define XPMDOUBLE 0x00000002
+#define XPMSTRING 0x00000004
+#define XPMFINISHED 0x00000008
+
+#define XPMCASESENSITIVE 0x00000001
+#define XPMCASENONSENSITIVE 0x00000002
+
+// ---------
+// - Enums -
+// ---------
+
+enum ReadState
+{
+ XPMREAD_OK,
+ XPMREAD_ERROR,
+ XPMREAD_NEED_MORE
+};
+
+// -------------
+// - XPMReader -
+// -------------
+
+class BitmapWriteAccess;
+class Graphic;
+
+class XPMReader : public GraphicReader
+{
+private:
+
+ SvStream& mrIStm;
+ Bitmap maBmp;
+ BitmapWriteAccess* mpAcc;
+ Bitmap maMaskBmp;
+ BitmapWriteAccess* mpMaskAcc;
+ long mnLastPos;
+
+ sal_uLong mnWidth;
+ sal_uLong mnHeight;
+ sal_uLong mnColors;
+ sal_uLong mnCpp; // characters per pix
+ sal_Bool mbTransparent;
+ sal_Bool mbStatus;
+ sal_uLong mnStatus;
+ sal_uLong mnIdentifier;
+ sal_uInt8 mcThisByte;
+ sal_uInt8 mcLastByte;
+ sal_uLong mnTempAvail;
+ sal_uInt8* mpTempBuf;
+ sal_uInt8* mpTempPtr;
+ sal_uInt8* mpFastColorTable;
+ sal_uInt8* mpColMap;
+ sal_uLong mnStringSize;
+ sal_uInt8* mpStringBuf;
+ sal_uLong mnParaSize;
+ sal_uInt8* mpPara;
+
+ sal_Bool ImplGetString( void );
+ sal_Bool ImplGetColor( sal_uLong );
+ sal_Bool ImplGetScanLine( sal_uLong );
+ sal_Bool ImplGetColSub( sal_uInt8* );
+ sal_Bool ImplGetColKey( sal_uInt8 );
+ void ImplGetRGBHex( sal_uInt8*, sal_uLong );
+ sal_Bool ImplGetPara( sal_uLong numb );
+ sal_Bool ImplCompare( sal_uInt8*, sal_uInt8*, sal_uLong, sal_uLong nmode = XPMCASENONSENSITIVE );
+ sal_uLong ImplGetULONG( sal_uLong nPara );
+
+public:
+ XPMReader( SvStream& rStm );
+ virtual ~XPMReader();
+
+ ReadState ReadXPM( Graphic& rGraphic );
+};
+
+#endif // _XPMPRIVATE
+
+// -------------
+// - ImportXPM -
+// -------------
+
+sal_Bool ImportXPM( SvStream& rStream, Graphic& rGraphic );
+
+#endif // _XPMREAD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/jpeg/jpeg.cxx b/vcl/source/filter/jpeg/jpeg.cxx
new file mode 100644
index 000000000000..6bd130d9a727
--- /dev/null
+++ b/vcl/source/filter/jpeg/jpeg.cxx
@@ -0,0 +1,777 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <tools/solar.h>
+
+extern "C"
+{
+ #include "stdio.h"
+ #include "jpeg.h"
+ #include "jpeglib.h"
+ #include "jerror.h"
+}
+
+#define _JPEGPRIVATE
+#include <vcl/bmpacc.hxx>
+#include "jpeg.hxx"
+#include <svtools/FilterConfigItem.hxx>
+#include <svtools/filter.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+using namespace ::com::sun::star;
+
+#define JPEGMINREAD 512
+
+// -------------
+// - (C-Calls) -
+// -------------
+
+// ------------------------------------------------------------------------
+
+extern "C" void* CreateBitmap( void* pJPEGReader, void* pJPEGCreateBitmapParam )
+{
+ return ( (JPEGReader*) pJPEGReader )->CreateBitmap( pJPEGCreateBitmapParam );
+}
+
+// ------------------------------------------------------------------------
+
+extern "C" void* GetScanline( void* pJPEGWriter, long nY )
+{
+ return ( (JPEGWriter*) pJPEGWriter )->GetScanline( nY );
+}
+
+// ------------------------------------------------------------------------
+
+struct JPEGCallbackStruct
+{
+ uno::Reference< task::XStatusIndicator > xStatusIndicator;
+};
+
+extern "C" long JPEGCallback( void* pCallbackData, long nPercent )
+{
+ JPEGCallbackStruct* pS = (JPEGCallbackStruct*)pCallbackData;
+ if ( pS && pS->xStatusIndicator.is() )
+ {
+ pS->xStatusIndicator->setValue( nPercent );
+ }
+ return 0L;
+}
+
+#define BUF_SIZE 4096
+
+typedef struct
+{
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ SvStream* outfile; /* target stream */
+ JOCTET * buffer; /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+extern "C" void init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ BUF_SIZE * sizeof(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = BUF_SIZE;
+}
+
+extern "C" boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ if (dest->outfile->Write(dest->buffer, BUF_SIZE) !=
+ (size_t) BUF_SIZE)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = BUF_SIZE;
+
+ return sal_True;
+}
+
+extern "C" void term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (dest->outfile->Write(dest->buffer, datacount) != datacount)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+}
+
+extern "C" void jpeg_svstream_dest (j_compress_ptr cinfo, void* out)
+{
+ SvStream * outfile = (SvStream*)out;
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_svstream_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+}
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ SvStream * infile; /* source stream */
+ JOCTET * buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+extern "C" void init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = sal_True;
+}
+
+long StreamRead( SvStream* pSvStm, void* pBuffer, long nBufferSize )
+{
+ long nRead = 0;
+
+ if( pSvStm->GetError() != ERRCODE_IO_PENDING )
+ {
+ long nActPos = pSvStm->Tell();
+
+ nRead = (long) pSvStm->Read( pBuffer, nBufferSize );
+
+ if( pSvStm->GetError() == ERRCODE_IO_PENDING )
+ {
+ // Damit wir wieder an die alte Position
+ // seeken koennen, setzen wir den Error temp.zurueck
+ pSvStm->ResetError();
+ pSvStm->Seek( nActPos );
+ pSvStm->SetError( ERRCODE_IO_PENDING );
+ }
+ }
+
+ return nRead;
+}
+
+extern "C" boolean fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = StreamRead(src->infile, src->buffer, BUF_SIZE);
+
+ if (!nbytes) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = sal_False;
+
+ return sal_True;
+}
+
+extern "C" void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ /* note we assume that fill_input_buffer will never return sal_False,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+extern "C" void term_source (j_decompress_ptr)
+{
+ /* no work necessary here */
+}
+
+extern "C" void jpeg_svstream_src (j_decompress_ptr cinfo, void * in)
+{
+ my_src_ptr src;
+ SvStream * infile = (SvStream*)in;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ BUF_SIZE * sizeof(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
+
+// --------------
+// - JPEGReader -
+// --------------
+
+JPEGReader::JPEGReader( SvStream& rStm, void* /*pCallData*/, sal_Bool bSetLS ) :
+ rIStm ( rStm ),
+ pAcc ( NULL ),
+ pAcc1 ( NULL ),
+ pBuffer ( NULL ),
+ nLastPos ( rStm.Tell() ),
+ nLastLines ( 0 ),
+ bSetLogSize ( bSetLS )
+{
+ maUpperName = rtl::OUString("SVIJPEG");
+ nFormerPos = nLastPos;
+}
+
+// ------------------------------------------------------------------------
+
+JPEGReader::~JPEGReader()
+{
+ if( pBuffer )
+ rtl_freeMemory( pBuffer );
+
+ if( pAcc )
+ aBmp.ReleaseAccess( pAcc );
+
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+}
+
+// ------------------------------------------------------------------------
+
+void* JPEGReader::CreateBitmap( void* _pParam )
+{
+ JPEGCreateBitmapParam *pParam = (JPEGCreateBitmapParam *) _pParam;
+
+ if (pParam->nWidth > SAL_MAX_INT32/8 || pParam->nHeight > SAL_MAX_INT32/8)
+ return NULL; // avoid overflows later
+
+ Size aSize( pParam->nWidth, pParam->nHeight );
+ sal_Bool bGray = pParam->bGray != 0;
+
+ void* pBmpBuf = NULL;
+
+ if( pAcc )
+ aBmp.ReleaseAccess( pAcc );
+
+ sal_uInt64 nSize = aSize.Width();
+ nSize *= aSize.Height();
+ if (nSize > SAL_MAX_INT32 / 24)
+ return NULL;
+
+ if( bGray )
+ {
+ BitmapPalette aGrayPal( 256 );
+
+ for( sal_uInt16 n = 0; n < 256; n++ )
+ {
+ const sal_uInt8 cGray = (sal_uInt8) n;
+ aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
+ }
+
+ aBmp = Bitmap( aSize, 8, &aGrayPal );
+ }
+ else
+ aBmp = Bitmap( aSize, 24 );
+
+ if ( bSetLogSize )
+ {
+ unsigned long nUnit = ((JPEGCreateBitmapParam*)pParam)->density_unit;
+
+ if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) &&
+ pParam->X_density && pParam->Y_density )
+ {
+ Point aEmptyPoint;
+ Fraction aFractX( 1, pParam->X_density );
+ Fraction aFractY( 1, pParam->Y_density );
+ MapMode aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY );
+ Size aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM );
+
+ aBmp.SetPrefSize( aPrefSize );
+ aBmp.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
+ }
+ }
+
+ pAcc = aBmp.AcquireWriteAccess();
+
+ if( pAcc )
+ {
+ const sal_uLong nFormat = pAcc->GetScanlineFormat();
+
+ if(
+ ( bGray && ( BMP_FORMAT_8BIT_PAL == nFormat ) ) ||
+ ( !bGray && ( BMP_FORMAT_24BIT_TC_RGB == nFormat ) )
+ )
+ {
+ pBmpBuf = pAcc->GetBuffer();
+ pParam->nAlignedWidth = pAcc->GetScanlineSize();
+ pParam->bTopDown = pAcc->IsTopDown();
+ }
+ else
+ {
+ pParam->nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) );
+ pParam->bTopDown = sal_True;
+ pBmpBuf = pBuffer = rtl_allocateMemory( pParam->nAlignedWidth * aSize.Height() );
+ }
+ }
+
+ // clean up, if no Bitmap buffer can be provided.
+ if ( !pBmpBuf )
+ {
+ aBmp.ReleaseAccess( pAcc );
+ pAcc = NULL;
+ }
+
+ return pBmpBuf;
+}
+
+// ------------------------------------------------------------------------
+
+void JPEGReader::FillBitmap()
+{
+ if( pBuffer && pAcc )
+ {
+ HPBYTE pTmp;
+ BitmapColor aColor;
+ long nAlignedWidth;
+ long nWidth = pAcc->Width();
+ long nHeight = pAcc->Height();
+
+ if( pAcc->GetBitCount() == 8 )
+ {
+ BitmapColor* pCols = new BitmapColor[ 256 ];
+
+ for( sal_uInt16 n = 0; n < 256; n++ )
+ {
+ const sal_uInt8 cGray = (sal_uInt8) n;
+ pCols[ n ] = pAcc->GetBestMatchingColor( BitmapColor( cGray, cGray, cGray ) );
+ }
+
+ nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 8L );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ pAcc->SetPixel( nY, nX, pCols[ *pTmp++ ] );
+ }
+
+ delete[] pCols;
+ }
+ else
+ {
+ nAlignedWidth = AlignedWidth4Bytes( pAcc->Width() * 24L );
+
+ for( long nY = 0L; nY < nHeight; nY++ )
+ {
+ pTmp = (sal_uInt8*) pBuffer + nY * nAlignedWidth;
+
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor.SetRed( *pTmp++ );
+ aColor.SetGreen( *pTmp++ );
+ aColor.SetBlue( *pTmp++ );
+ pAcc->SetPixel( nY, nX, aColor );
+ }
+ }
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+Graphic JPEGReader::CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines )
+{
+ Graphic aGraphic;
+ const Size aSizePix( rBitmap.GetSizePixel() );
+
+ if( !nLastLines )
+ {
+ if( pAcc1 )
+ aBmp1.ReleaseAccess( pAcc1 );
+
+ aBmp1 = Bitmap( rBitmap.GetSizePixel(), 1 );
+ aBmp1.Erase( Color( COL_WHITE ) );
+ pAcc1 = aBmp1.AcquireWriteAccess();
+ }
+
+ if( nLines && ( nLines < aSizePix.Height() ) )
+ {
+ if( pAcc1 )
+ {
+ const long nNewLines = nLines - nLastLines;
+
+ if( nNewLines )
+ {
+ pAcc1->SetFillColor( Color( COL_BLACK ) );
+ pAcc1->FillRect( Rectangle( Point( 0, nLastLines ),
+ Size( pAcc1->Width(), nNewLines ) ) );
+ }
+
+ aBmp1.ReleaseAccess( pAcc1 );
+ aGraphic = BitmapEx( rBitmap, aBmp1 );
+ pAcc1 = aBmp1.AcquireWriteAccess();
+ }
+ else
+ aGraphic = rBitmap;
+ }
+ else
+ aGraphic = rBitmap;
+
+ nLastLines = nLines;
+
+ return aGraphic;
+}
+
+// ------------------------------------------------------------------------
+
+ReadState JPEGReader::Read( Graphic& rGraphic )
+{
+ long nEndPos;
+ long nLines;
+ ReadState eReadState;
+ sal_Bool bRet = sal_False;
+ sal_uInt8 cDummy;
+
+#if 1 // TODO: is it possible to get rid of this seek to the end?
+ // check if the stream's end is already available
+ rIStm.Seek( STREAM_SEEK_TO_END );
+ rIStm >> cDummy;
+ nEndPos = rIStm.Tell();
+
+ // else check if at least JPEGMINREAD bytes can be read
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ {
+ rIStm.ResetError();
+ if( ( nEndPos - nFormerPos ) < JPEGMINREAD )
+ {
+ rIStm.Seek( nLastPos );
+ return JPEGREAD_NEED_MORE;
+ }
+ }
+
+ // seek back to the original position
+ rIStm.Seek( nLastPos );
+#endif
+
+ Size aPreviewSize = GetPreviewSize();
+ SetJpegPreviewSizeHint( aPreviewSize.Width(), aPreviewSize.Height() );
+
+ // read the (partial) image
+ ReadJPEG( this, &rIStm, &nLines );
+
+ if( pAcc )
+ {
+ if( pBuffer )
+ {
+ FillBitmap();
+ rtl_freeMemory( pBuffer );
+ pBuffer = NULL;
+ }
+
+ aBmp.ReleaseAccess( pAcc );
+ pAcc = NULL;
+
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ rGraphic = CreateIntermediateGraphic( aBmp, nLines );
+ else
+ rGraphic = aBmp;
+
+ bRet = sal_True;
+ }
+ else if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ bRet = sal_True;
+
+ // Status setzen ( Pending hat immer Vorrang )
+ if( rIStm.GetError() == ERRCODE_IO_PENDING )
+ {
+ eReadState = JPEGREAD_NEED_MORE;
+ rIStm.ResetError();
+ nFormerPos = rIStm.Tell();
+ }
+ else
+ {
+ if( bRet )
+ eReadState = JPEGREAD_OK;
+ else
+ eReadState = JPEGREAD_ERROR;
+ }
+
+ return eReadState;
+}
+
+
+// --------------
+// - JPEGWriter -
+// --------------
+
+JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) :
+ rOStm ( rStm ),
+ pAcc ( NULL ),
+ pBuffer ( NULL ),
+ pExpWasGrey ( pExportWasGrey )
+{
+ FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData );
+ bGreys = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) ), 0 ) != 0;
+ nQuality = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Quality" ) ), 75 );
+
+ if ( pFilterData )
+ {
+ int nArgs = pFilterData->getLength();
+ const beans::PropertyValue* pValues = pFilterData->getConstArray();
+ while( nArgs-- )
+ {
+ if ( pValues->Name == "StatusIndicator" )
+ {
+ pValues->Value >>= xStatusIndicator;
+ }
+ pValues++;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void* JPEGWriter::GetScanline( long nY )
+{
+ void* pScanline = NULL;
+
+ if( pAcc )
+ {
+ if( bNative )
+ pScanline = pAcc->GetScanline( nY );
+ else if( pBuffer )
+ {
+ BitmapColor aColor;
+ long nWidth = pAcc->Width();
+ sal_uInt8* pTmp = pBuffer;
+
+ if( pAcc->HasPalette() )
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) );
+ *pTmp++ = aColor.GetRed();
+ if ( bGreys )
+ continue;
+ *pTmp++ = aColor.GetGreen();
+ *pTmp++ = aColor.GetBlue();
+ }
+ }
+ else
+ {
+ for( long nX = 0L; nX < nWidth; nX++ )
+ {
+ aColor = pAcc->GetPixel( nY, nX );
+ *pTmp++ = aColor.GetRed();
+ if ( bGreys )
+ continue;
+ *pTmp++ = aColor.GetGreen();
+ *pTmp++ = aColor.GetBlue();
+ }
+ }
+
+ pScanline = pBuffer;
+ }
+ }
+
+ return pScanline;
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool JPEGWriter::Write( const Graphic& rGraphic )
+{
+ sal_Bool bRet = sal_False;
+
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+
+ Bitmap aGraphicBmp( rGraphic.GetBitmap() );
+
+ if ( bGreys )
+ {
+ if ( !aGraphicBmp.Convert( BMP_CONVERSION_8BIT_GREYS ) )
+ aGraphicBmp = rGraphic.GetBitmap();
+ }
+
+ pAcc = aGraphicBmp.AcquireReadAccess();
+
+ if ( !bGreys ) // bitmap was not explicitly converted into greyscale,
+ { // check if source is greyscale only
+
+ sal_Bool bIsGrey = sal_True;
+
+ long nWidth = pAcc->Width();
+ for ( long nY = 0; bIsGrey && ( nY < pAcc->Height() ); nY++ )
+ {
+ BitmapColor aColor;
+ for( long nX = 0L; bIsGrey && ( nX < nWidth ); nX++ )
+ {
+ aColor = pAcc->HasPalette() ? pAcc->GetPaletteColor( (sal_uInt8) pAcc->GetPixel( nY, nX ) )
+ : pAcc->GetPixel( nY, nX );
+ bIsGrey = ( aColor.GetRed() == aColor.GetGreen() ) && ( aColor.GetRed() == aColor.GetBlue() );
+ }
+ }
+ if ( bIsGrey )
+ bGreys = sal_True;
+ }
+
+ if( pExpWasGrey )
+ *pExpWasGrey = bGreys;
+
+ if( pAcc )
+ {
+ bNative = ( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB );
+
+ if( !bNative )
+ pBuffer = new sal_uInt8[ AlignedWidth4Bytes( bGreys ? pAcc->Width() * 8L : pAcc->Width() * 24L ) ];
+
+ JPEGCallbackStruct aCallbackData;
+ aCallbackData.xStatusIndicator = xStatusIndicator;
+ bRet = (sal_Bool) WriteJPEG( this, &rOStm, pAcc->Width(), pAcc->Height(), bGreys, nQuality, &aCallbackData );
+
+ delete[] pBuffer;
+ pBuffer = NULL;
+
+ aGraphicBmp.ReleaseAccess( pAcc );
+ pAcc = NULL;
+ }
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+
+ return bRet;
+}
+
+// --------------
+// - ImportJPEG -
+// --------------
+
+sal_Bool ImportJPEG( SvStream& rStm, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags )
+{
+ JPEGReader* pJPEGReader = (JPEGReader*) rGraphic.GetContext();
+ ReadState eReadState;
+ sal_Bool bRet = sal_True;
+
+ if( !pJPEGReader )
+ pJPEGReader = new JPEGReader( rStm, pCallerData, ( nImportFlags & GRFILTER_I_FLAGS_SET_LOGSIZE_FOR_JPEG ) != 0 );
+
+ if( nImportFlags & GRFILTER_I_FLAGS_FOR_PREVIEW )
+ pJPEGReader->SetPreviewSize( Size(128,128) );
+ else
+ pJPEGReader->DisablePreviewMode();
+
+ rGraphic.SetContext( NULL );
+ eReadState = pJPEGReader->Read( rGraphic );
+
+ if( eReadState == JPEGREAD_ERROR )
+ {
+ bRet = sal_False;
+ delete pJPEGReader;
+ }
+ else if( eReadState == JPEGREAD_OK )
+ delete pJPEGReader;
+ else
+ rGraphic.SetContext( pJPEGReader );
+
+ return bRet;
+}
+
+// --------------
+// - ExportJPEG -
+// --------------
+
+sal_Bool ExportJPEG( SvStream& rOStm, const Graphic& rGraphic,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
+ bool* pExportWasGrey
+ )
+{
+ JPEGWriter aJPEGWriter( rOStm, pFilterData, pExportWasGrey );
+ return aJPEGWriter.Write( rGraphic );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/jpeg/jpeg.h b/vcl/source/filter/jpeg/jpeg.h
new file mode 100644
index 000000000000..9c7e4b71d6a0
--- /dev/null
+++ b/vcl/source/filter/jpeg/jpeg.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _JPEG_H
+#define _JPEG_H
+
+#if defined( ICC )
+#include <stdio.h>
+#endif
+
+#if defined (UNX) || defined(__MINGW32__)
+#include <sys/types.h>
+#endif
+
+struct JPEGCreateBitmapParam
+{
+ unsigned long nWidth;
+ unsigned long nHeight;
+ unsigned long density_unit;
+ unsigned long X_density;
+ unsigned long Y_density;
+ long bGray;
+
+ long nAlignedWidth; // these members will be filled by the
+ long bTopDown; // CreateBitmap method in svtools
+};
+
+typedef struct my_error_mgr* my_error_ptr;
+typedef unsigned char* HPBYTE;
+
+void* JPEGMalloc( size_t size );
+void JPEGFree( void *ptr );
+long JPEGCallback( void* pCallbackData, long nPercent );
+
+long WriteJPEG( void* pJPEGWriter, void* pOStm, long nWidth, long nHeight, long bGreyScale,
+ long nQualityPercent, void* pCallbackData );
+void* GetScanline( void* pJPEGWriter, long nY );
+
+void ReadJPEG( void* pJPEGReader, void* pIStm, long* pLines );
+void* CreateBitmap( void* pJPEGReader, void* pJPEGCreateBitmapParam );
+
+/* TODO: when incompatible changes are possible again
+ the preview size hint should be redone */
+void SetJpegPreviewSizeHint( int nWidth, int nHeight );
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/jpeg/jpeg.hxx b/vcl/source/filter/jpeg/jpeg.hxx
new file mode 100644
index 000000000000..df033bd7b98b
--- /dev/null
+++ b/vcl/source/filter/jpeg/jpeg.hxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _JPEG_HXX
+#define _JPEG_HXX
+
+#include <vcl/graph.hxx>
+#include <svtools/fltcall.hxx>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+
+#ifdef _JPEGPRIVATE
+
+// --------
+// - Enum -
+// --------
+
+enum ReadState
+{
+ JPEGREAD_OK,
+ JPEGREAD_ERROR,
+ JPEGREAD_NEED_MORE
+};
+
+// --------------
+// - JPEGReader -
+// --------------
+
+class JPEGReader : public GraphicReader
+{
+ SvStream& rIStm;
+ Bitmap aBmp;
+ Bitmap aBmp1;
+ BitmapWriteAccess* pAcc;
+ BitmapWriteAccess* pAcc1;
+ void* pBuffer;
+ long nLastPos;
+ long nFormerPos;
+ long nLastLines;
+ sal_Bool bSetLogSize;
+
+ Graphic CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines );
+ void FillBitmap();
+
+public:
+
+ void* CreateBitmap( void* JPEGCreateBitmapParam );
+
+public:
+
+
+
+ JPEGReader( SvStream& rStm, void* pCallData, sal_Bool bSetLogSize );
+ virtual ~JPEGReader();
+
+
+ ReadState Read( Graphic& rGraphic );
+};
+
+// --------------
+// - JPEGWriter -
+// --------------
+
+class JPEGWriter
+{
+ SvStream& rOStm;
+ Bitmap aBmp;
+ BitmapReadAccess* pAcc;
+ sal_uInt8* pBuffer;
+ sal_Bool bNative;
+
+ sal_Bool bGreys;
+ sal_Int32 nQuality;
+
+ bool* pExpWasGrey;
+
+ com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+public:
+
+ void* GetScanline( long nY );
+
+ JPEGWriter( SvStream& rOStm, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
+ bool* pExportWasGrey = NULL );
+ ~JPEGWriter() {};
+
+ sal_Bool Write( const Graphic& rGraphic );
+};
+
+#endif // _JPEGPRIVATE
+
+// ---------------------
+// - Import/ExportJPEG -
+// ---------------------
+
+sal_Bool ImportJPEG( SvStream& rStream, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags );
+
+sal_Bool ExportJPEG( SvStream& rStream,
+ const Graphic& rGraphic,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData,
+ bool* pExportWasGrey = NULL
+ );
+
+#endif // _JPEG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/jpeg/jpegc.c b/vcl/source/filter/jpeg/jpegc.c
new file mode 100644
index 000000000000..528e19e51216
--- /dev/null
+++ b/vcl/source/filter/jpeg/jpegc.c
@@ -0,0 +1,278 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "setjmp.h"
+#include "jpeglib.h"
+#include "jerror.h"
+#include "jpeg.h"
+#include "rtl/alloc.h"
+#include "osl/diagnose.h"
+
+struct my_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+void jpeg_svstream_src (j_decompress_ptr cinfo, void* infile);
+void jpeg_svstream_dest (j_compress_ptr cinfo, void* outfile);
+
+METHODDEF( void )
+my_error_exit (j_common_ptr cinfo)
+{
+ my_error_ptr myerr = (my_error_ptr) cinfo->err;
+ (*cinfo->err->output_message) (cinfo);
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+METHODDEF( void )
+my_output_message (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message) (cinfo, buffer);
+}
+
+/* TODO: when incompatible changes are possible again
+ the preview size hint should be redone */
+static int nPreviewWidth = 0;
+static int nPreviewHeight = 0;
+void SetJpegPreviewSizeHint( int nWidth, int nHeight )
+{
+ nPreviewWidth = nWidth;
+ nPreviewHeight = nHeight;
+}
+
+void ReadJPEG( void* pJPEGReader, void* pIStm, long* pLines )
+{
+ struct jpeg_decompress_struct cinfo;
+ struct my_error_mgr jerr;
+ struct JPEGCreateBitmapParam aCreateBitmapParam;
+ HPBYTE pDIB;
+ HPBYTE pTmp;
+ long nWidth;
+ long nHeight;
+ long nAlignedWidth;
+ JSAMPLE * range_limit;
+ HPBYTE pScanLineBuffer = NULL;
+ long nScanLineBufferComponents = 0;
+ // declare bDecompCreated volatile because of gcc
+ // warning: variable 'bDecompCreated' might be clobbered by `longjmp' or `vfork'
+ volatile long bDecompCreated = 0;
+
+ /* Falls der Stream nicht ausreicht (IO_PENDING)
+ wird ueber ein longjmp in der Schleife nach Exit
+ gesprungen, wir geben dann die Anzahl
+ der bisher bearbeiteten Scanlines zurueck*/
+ if ( setjmp( jerr.setjmp_buffer ) )
+ goto Exit;
+
+ cinfo.err = jpeg_std_error( &jerr.pub );
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+
+ jpeg_create_decompress( &cinfo );
+ bDecompCreated = 1;
+ jpeg_svstream_src( &cinfo, pIStm );
+ jpeg_read_header( &cinfo, sal_True );
+
+ cinfo.scale_num = 1;
+ cinfo.scale_denom = 1;
+ cinfo.output_gamma = 1.0;
+ cinfo.raw_data_out = sal_False;
+ cinfo.quantize_colors = sal_False;
+ if ( cinfo.jpeg_color_space == JCS_YCbCr )
+ cinfo.out_color_space = JCS_RGB;
+ else if ( cinfo.jpeg_color_space == JCS_YCCK )
+ cinfo.out_color_space = JCS_CMYK;
+
+ OSL_ASSERT(cinfo.out_color_space == JCS_CMYK || cinfo.out_color_space == JCS_GRAYSCALE || cinfo.out_color_space == JCS_RGB);
+
+ /* change scale for preview import */
+ if( nPreviewWidth || nPreviewHeight )
+ {
+ if( nPreviewWidth == 0 ) {
+ nPreviewWidth = ( cinfo.image_width*nPreviewHeight )/cinfo.image_height;
+ if( nPreviewWidth <= 0 )
+ nPreviewWidth = 1;
+ } else if( nPreviewHeight == 0 ) {
+ nPreviewHeight = ( cinfo.image_height*nPreviewWidth )/cinfo.image_width;
+ if( nPreviewHeight <= 0 )
+ nPreviewHeight = 1;
+ }
+
+ for( cinfo.scale_denom = 1; cinfo.scale_denom < 8; cinfo.scale_denom *= 2 )
+ {
+ if( cinfo.image_width < nPreviewWidth * cinfo.scale_denom )
+ break;
+ if( cinfo.image_height < nPreviewHeight * cinfo.scale_denom )
+ break;
+ }
+
+ if( cinfo.scale_denom > 1 )
+ {
+ cinfo.dct_method = JDCT_FASTEST;
+ cinfo.do_fancy_upsampling = sal_False;
+ cinfo.do_block_smoothing = sal_False;
+ }
+ }
+
+ jpeg_start_decompress( &cinfo );
+
+ nWidth = cinfo.output_width;
+ nHeight = cinfo.output_height;
+ aCreateBitmapParam.nWidth = nWidth;
+ aCreateBitmapParam.nHeight = nHeight;
+
+ aCreateBitmapParam.density_unit = cinfo.density_unit;
+ aCreateBitmapParam.X_density = cinfo.X_density;
+ aCreateBitmapParam.Y_density = cinfo.Y_density;
+ aCreateBitmapParam.bGray = cinfo.output_components == 1;
+ pDIB = CreateBitmap( pJPEGReader, &aCreateBitmapParam );
+ nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
+ range_limit=cinfo.sample_range_limit;
+
+ if ( cinfo.out_color_space == JCS_CMYK )
+ {
+ nScanLineBufferComponents = cinfo.output_width * 4;
+ pScanLineBuffer = rtl_allocateMemory( nScanLineBufferComponents );
+ }
+
+ if( pDIB )
+ {
+ if( aCreateBitmapParam.bTopDown )
+ pTmp = pDIB;
+ else
+ {
+ pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
+ nAlignedWidth = -nAlignedWidth;
+ }
+
+ for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
+ {
+ if (pScanLineBuffer!=NULL) { // in other words cinfo.out_color_space == JCS_CMYK
+ int i;
+ int j;
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pScanLineBuffer, 1 );
+ // convert CMYK to RGB
+ for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
+ {
+ int c_=255-pScanLineBuffer[i+0];
+ int m_=255-pScanLineBuffer[i+1];
+ int y_=255-pScanLineBuffer[i+2];
+ int k_=255-pScanLineBuffer[i+3];
+ pTmp[j+0]=range_limit[ 255L - ( c_ + k_ ) ];
+ pTmp[j+1]=range_limit[ 255L - ( m_ + k_ ) ];
+ pTmp[j+2]=range_limit[ 255L - ( y_ + k_ ) ];
+ }
+ } else {
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY) &pTmp, 1 );
+ }
+ /* PENDING ??? */
+ if ( cinfo.err->msg_code == 113 )
+ break;
+
+ pTmp += nAlignedWidth;
+ }
+ }
+
+ jpeg_finish_decompress( &cinfo );
+ if (pScanLineBuffer!=NULL) {
+ rtl_freeMemory( pScanLineBuffer );
+ pScanLineBuffer=NULL;
+ }
+
+Exit:
+
+ if( bDecompCreated )
+ jpeg_destroy_decompress( &cinfo );
+}
+
+long WriteJPEG( void* pJPEGWriter, void* pOStm,
+ long nWidth, long nHeight, long bGreys,
+ long nQualityPercent, void* pCallbackData )
+{
+ struct jpeg_compress_struct cinfo;
+ struct my_error_mgr jerr;
+ void* pScanline;
+ long nY;
+ // declare bCompCreated, bRet volatile because of gcc
+ // warning: variable 'bCompCreated' might be clobbered by `longjmp' or `vfork'
+ volatile long bCompCreated = 0;
+ volatile long bRet = 0;
+
+ if ( setjmp( jerr.setjmp_buffer ) )
+ goto Exit;
+
+ cinfo.err = jpeg_std_error( &jerr.pub );
+ jerr.pub.error_exit = my_error_exit;
+ jerr.pub.output_message = my_output_message;
+
+ jpeg_create_compress( &cinfo );
+ bCompCreated = 1;
+
+ jpeg_svstream_dest( &cinfo, pOStm );
+
+ cinfo.image_width = (JDIMENSION) nWidth;
+ cinfo.image_height = (JDIMENSION) nHeight;
+ if ( bGreys )
+ {
+ cinfo.input_components = 1;
+ cinfo.in_color_space = JCS_GRAYSCALE;
+ }
+ else
+ {
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+ }
+
+ jpeg_set_defaults( &cinfo );
+ jpeg_set_quality( &cinfo, (int) nQualityPercent, sal_False );
+
+ if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
+ jpeg_simple_progression( &cinfo );
+
+ jpeg_start_compress( &cinfo, sal_True );
+
+ for( nY = 0; nY < nHeight; nY++ )
+ {
+ pScanline = GetScanline( pJPEGWriter, nY );
+
+ if( pScanline )
+ jpeg_write_scanlines( &cinfo, (JSAMPARRAY) &pScanline, 1 );
+
+ if( JPEGCallback( pCallbackData, nY * 100L / nHeight ) )
+ goto Exit;
+ }
+
+ bRet = 1;
+
+ jpeg_finish_compress(&cinfo);
+
+Exit:
+
+ if ( bCompCreated )
+ jpeg_destroy_compress( &cinfo );
+
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgf.ini b/vcl/source/filter/sgf.ini
new file mode 100644
index 000000000000..17c01255b6f1
--- /dev/null
+++ b/vcl/source/filter/sgf.ini
@@ -0,0 +1,136 @@
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+#
+
+#Family : (Roman,Swiss,Modern,Script,Decora);
+#CharSet : (Ansi,IBMPC,Mac,Symbol,System); Default is System
+#Attribute: (Bold,Ital,Sans,Serf,Fixd);
+
+[SGV Fonts fuer StarView]
+#IF-ID Fontname Attribute SV-Fam ChSet Width FontName
+ 3848=(ITC Zapf Dingbats) Decora ()
+ 5720=(Symbol) Serf Decora Symbol ()
+ 5721=(Symbol) Bold Serf Decora Symbol ()
+ 5723=(Symbol Sans) Sans Decora Symbol ()
+ 5724=(Symbol Sans) Bold Sans Decora Symbol ()
+ 90133=(Dom Casual) Sans Script ()
+ 90326=(Brush) Bold Ital Serf Script ()
+ 90349=(Park Avenue) Ital Serf Script ()
+ 90508=(Uncial) Sans Roman ()
+ 91118=(Antique Olive) Bold Sans Swiss ()
+ 91119=(Antique Olive) Sans Swiss ()
+ 91120=(Antique Olive Compact) Bold Sans Swiss ()
+ 91335=(ITC Benguiat) Bold Serf Roman ()
+ 91336=(ITC Benguiat) Bold Ital Serf Roman ()
+ 91846=(Antique Olive) Ital Sans Roman ()
+#92500=(CG Times) Serf Roman ()
+#92501=(CG Times) Ital Serf Roman ()
+#92504=(CG Times) Bold Serf Roman ()
+#92505=(CG Times) Bold Ital Serf Roman ()
+#93950=(Courier) Serf Fixd Modern ()
+#93951=(Courier) Ital Serf Fixd Modern ()
+#93952=(Courier) Bold Serf Fixd Modern ()
+#93953=(Courier) Bold Ital Serf Fixd Modern ()
+#94021=(Univers) Sans Swiss ()
+#94022=(Univers) Ital Sans Swiss ()
+#94023=(Univers) Bold Sans Swiss ()
+#94024=(Univers) Bold Ital Sans Swiss ()
+102004=(Avanti) Bold Ital Sans Swiss ()
+102005=(Avanti) Ital Sans Swiss ()
+102007=(Booklet) Bold Sans Roman ()
+102008=(Booklet) Bold Ital Sans Roman ()
+102009=(Booklet) Ital Sans Roman ()
+102010=(Centuri) Sans Roman ()
+102011=(Centuri) Bold Sans Roman ()
+102012=(Centuri) Bold Ital Sans Roman ()
+102013=(Centuri) Ital Sans Roman ()
+102014=(Paltus) Bold Sans Roman ()
+102015=(Paltus) Sans Roman ()
+102016=(Paltus) Bold Ital Sans Roman ()
+102017=(Paltus) Ital Sans Roman ()
+102018=(Sans) Sans Swiss ()
+102019=(Sans) Bold Sans Swiss ()
+102020=(Sans) Bold Ital Sans Swiss ()
+102021=(Sans) Ital Sans Swiss ()
+102022=(SansCondensed) Sans Swiss ()
+102023=(SansCondensed) Bold Sans Swiss ()
+102024=(SansCondensed) Bold Ital Sans Swiss ()
+102025=(SansCondensed) Ital Sans Swiss ()
+102026=(PS-Roman) Sans Roman ()
+102027=(PS-Roman) Bold Sans Roman ()
+102028=(PS-Roman) Bold Ital Sans Roman ()
+102029=(PS-Roman) Ital Sans Roman ()
+200111=(Chalenge) Sans ()
+200112=(Chalenge) Bold Sans ()
+200113=(Chalenge) Ital Sans ()
+200114=(Chalenge) Bold Ital Sans ()
+200121=(Office) Sans ()
+200122=(Office) Bold Sans ()
+200123=(Office) Ital Sans ()
+200124=(Office) Bold Ital Sans ()
+200131=(Milano) Sans ()
+200132=(Milano) Bold Sans ()
+200133=(Milano) Ital Sans ()
+200134=(Milano) Bold Ital Sans ()
+200141=(Atlantic) Sans Roman ()
+200142=(Atlantic) Bold Sans Roman ()
+200143=(Atlantic) Ital Sans Roman ()
+200144=(Atlantic) Bold Ital Sans Roman ()
+200151=(Pentagon) Sans ()
+200152=(Pentagon) Bold Sans ()
+200153=(Pentagon) Ital Sans ()
+200154=(Pentagon) Bold Ital Sans ()
+200161=(Classico) Sans ()
+200162=(Classico) Bold Sans ()
+200163=(Classico) Ital Sans ()
+200164=(Classico) Bold Ital Sans ()
+200211=(Westcost) Sans ()
+200212=(Westcost) Bold Sans ()
+200213=(Westcost) Ital Sans ()
+200214=(Westcost) Bold Ital Sans ()
+200221=(Finish) Sans ()
+200222=(Finish) Bold Sans ()
+200223=(Finish) Ital Sans ()
+200224=(Finish) Bold Ital Sans ()
+200231=(Classic) Sans ()
+200232=(Classic) Bold Sans ()
+200233=(Classic) Ital Sans ()
+200234=(Classic) Bold Ital Sans ()
+200241=(Hilton) Sans ()
+200242=(Hilton) Bold Sans ()
+200243=(Hilton) Ital Sans ()
+200244=(Hilton) Bold Ital Sans ()
+200251=(Progress) Sans ()
+200252=(Progress) Bold Sans ()
+200253=(Progress) Ital Sans ()
+200254=(Progress) Bold Ital Sans ()
+200261=(PrestigeElite) Sans ()
+200262=(PrestigeElite) Bold Sans ()
+200263=(PrestigeElite) Ital Sans ()
+200271=(Ovetti) Bold Sans ()
+200272=(Ovetti) Sans ()
+200301=(Cescendo) Sans ()
+200302=(Funky) Sans Decora ()
+200303=(Speed) Sans Decora ()
+200304=(Skyline) Sans Decora ()
+200305=(Calculator) Sans Decora ()
+200306=(Xpress) Sans Decora ()
+200307=(Console) Sans Decora ()
+200308=(Paisley) Sans ()
+200309=(Nova) Sans ()
+200310=(New York) Sans Decora ()
+200311=(Shanghai) Sans Decora ()
diff --git a/vcl/source/filter/sgfbram.cxx b/vcl/source/filter/sgfbram.cxx
new file mode 100644
index 000000000000..f698329a0c6d
--- /dev/null
+++ b/vcl/source/filter/sgfbram.cxx
@@ -0,0 +1,532 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <string.h>
+#include <osl/endian.h>
+#include <tools/stream.hxx>
+#include <vcl/gdimtf.hxx>
+#include <tools/color.hxx>
+#include <vcl/virdev.hxx>
+#include "sgffilt.hxx"
+#include "sgfbram.hxx"
+
+SvStream& operator>>(SvStream& rIStream, SgfHeader& rHead)
+{
+ rIStream.Read((char*)&rHead.Magic,SgfHeaderSize);
+#if defined OSL_BIGENDIAN
+ rHead.Magic =OSL_SWAPWORD(rHead.Magic );
+ rHead.Version=OSL_SWAPWORD(rHead.Version);
+ rHead.Typ =OSL_SWAPWORD(rHead.Typ );
+ rHead.Xsize =OSL_SWAPWORD(rHead.Xsize );
+ rHead.Ysize =OSL_SWAPWORD(rHead.Ysize );
+ rHead.Xoffs =OSL_SWAPWORD(rHead.Xoffs );
+ rHead.Yoffs =OSL_SWAPWORD(rHead.Yoffs );
+ rHead.Planes =OSL_SWAPWORD(rHead.Planes );
+ rHead.SwGrCol=OSL_SWAPWORD(rHead.SwGrCol);
+ rHead.OfsLo =OSL_SWAPWORD(rHead.OfsLo );
+ rHead.OfsHi =OSL_SWAPWORD(rHead.OfsHi );
+#endif
+ return rIStream;
+}
+
+sal_Bool SgfHeader::ChkMagic()
+{ return Magic=='J'*256+'J'; }
+
+sal_uInt32 SgfHeader::GetOffset()
+{ return sal_uInt32(OfsLo)+0x00010000*sal_uInt32(OfsHi); }
+
+SvStream& operator>>(SvStream& rIStream, SgfEntry& rEntr)
+{
+ rIStream.Read((char*)&rEntr.Typ,SgfEntrySize);
+#if defined OSL_BIGENDIAN
+ rEntr.Typ =OSL_SWAPWORD(rEntr.Typ );
+ rEntr.iFrei=OSL_SWAPWORD(rEntr.iFrei);
+ rEntr.lFreiLo=OSL_SWAPWORD (rEntr.lFreiLo);
+ rEntr.lFreiHi=OSL_SWAPWORD (rEntr.lFreiHi);
+ rEntr.OfsLo=OSL_SWAPWORD(rEntr.OfsLo);
+ rEntr.OfsHi=OSL_SWAPWORD(rEntr.OfsHi);
+#endif
+ return rIStream;
+}
+
+sal_uInt32 SgfEntry::GetOffset()
+{ return sal_uInt32(OfsLo)+0x00010000*sal_uInt32(OfsHi); }
+
+SvStream& operator>>(SvStream& rIStream, SgfVector& rVect)
+{
+ rIStream.Read((char*)&rVect,sizeof(rVect));
+#if defined OSL_BIGENDIAN
+ rVect.Flag =OSL_SWAPWORD(rVect.Flag );
+ rVect.x =OSL_SWAPWORD(rVect.x );
+ rVect.y =OSL_SWAPWORD(rVect.y );
+ rVect.OfsLo=OSL_SWAPDWORD (rVect.OfsLo);
+ rVect.OfsHi=OSL_SWAPDWORD (rVect.OfsHi);
+#endif
+ return rIStream;
+}
+
+SvStream& operator<<(SvStream& rOStream, BmpFileHeader& rHead)
+{
+#if defined OSL_BIGENDIAN
+ rHead.Typ =OSL_SWAPWORD(rHead.Typ );
+ rHead.SizeLo =OSL_SWAPWORD(rHead.SizeLo );
+ rHead.SizeHi =OSL_SWAPWORD(rHead.SizeHi );
+ rHead.Reserve1=OSL_SWAPWORD(rHead.Reserve1);
+ rHead.Reserve2=OSL_SWAPWORD(rHead.Reserve2);
+ rHead.OfsLo =OSL_SWAPWORD(rHead.OfsLo );
+ rHead.OfsHi =OSL_SWAPWORD(rHead.OfsHi );
+#endif
+ rOStream.Write((char*)&rHead,sizeof(rHead));
+#if defined OSL_BIGENDIAN
+ rHead.Typ =OSL_SWAPWORD(rHead.Typ );
+ rHead.SizeLo =OSL_SWAPWORD(rHead.SizeLo );
+ rHead.SizeHi =OSL_SWAPWORD(rHead.SizeHi );
+ rHead.Reserve1=OSL_SWAPWORD(rHead.Reserve1);
+ rHead.Reserve2=OSL_SWAPWORD(rHead.Reserve2);
+ rHead.OfsLo =OSL_SWAPWORD(rHead.OfsLo );
+ rHead.OfsHi =OSL_SWAPWORD(rHead.OfsHi );
+#endif
+ return rOStream;
+}
+
+void BmpFileHeader::SetSize(sal_uInt32 Size)
+{
+ SizeLo=sal_uInt16(Size & 0x0000FFFF);
+ SizeHi=sal_uInt16((Size & 0xFFFF0000)>>16);
+}
+
+void BmpFileHeader::SetOfs(sal_uInt32 Ofs)
+{
+ OfsLo=sal_uInt16(Ofs & 0x0000FFFF);
+ OfsHi=sal_uInt16((Ofs & 0xFFFF0000)>>16);
+}
+
+sal_uInt32 BmpFileHeader::GetOfs()
+{
+ return sal_uInt32(OfsLo)+0x00010000*sal_uInt32(OfsHi);
+}
+
+SvStream& operator<<(SvStream& rOStream, BmpInfoHeader& rInfo)
+{
+#if defined OSL_BIGENDIAN
+ rInfo.Size =OSL_SWAPDWORD (rInfo.Size );
+ rInfo.Width =OSL_SWAPDWORD (rInfo.Width );
+ rInfo.Hight =OSL_SWAPDWORD (rInfo.Hight );
+ rInfo.Planes =OSL_SWAPWORD(rInfo.Planes );
+ rInfo.PixBits =OSL_SWAPWORD(rInfo.PixBits );
+ rInfo.Compress=OSL_SWAPDWORD (rInfo.Compress);
+ rInfo.ImgSize =OSL_SWAPDWORD (rInfo.ImgSize );
+ rInfo.xDpmm =OSL_SWAPDWORD (rInfo.xDpmm );
+ rInfo.yDpmm =OSL_SWAPDWORD (rInfo.yDpmm );
+ rInfo.ColUsed =OSL_SWAPDWORD (rInfo.ColUsed );
+ rInfo.ColMust =OSL_SWAPDWORD (rInfo.ColMust );
+#endif
+ rOStream.Write((char*)&rInfo,sizeof(rInfo));
+#if defined OSL_BIGENDIAN
+ rInfo.Size =OSL_SWAPDWORD (rInfo.Size );
+ rInfo.Width =OSL_SWAPDWORD (rInfo.Width );
+ rInfo.Hight =OSL_SWAPDWORD (rInfo.Hight );
+ rInfo.Planes =OSL_SWAPWORD(rInfo.Planes );
+ rInfo.PixBits =OSL_SWAPWORD(rInfo.PixBits );
+ rInfo.Compress=OSL_SWAPDWORD (rInfo.Compress);
+ rInfo.ImgSize =OSL_SWAPDWORD (rInfo.ImgSize );
+ rInfo.xDpmm =OSL_SWAPDWORD (rInfo.xDpmm );
+ rInfo.yDpmm =OSL_SWAPDWORD (rInfo.yDpmm );
+ rInfo.ColUsed =OSL_SWAPDWORD (rInfo.ColUsed );
+ rInfo.ColMust =OSL_SWAPDWORD (rInfo.ColMust );
+#endif
+ return rOStream;
+}
+
+SvStream& operator<<(SvStream& rOStream, const RGBQuad& rQuad)
+{
+ rOStream.Write((char*)&rQuad,sizeof(rQuad));
+ return rOStream;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// PcxExpand ///////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+class PcxExpand
+{
+private:
+ sal_uInt16 Count;
+ sal_uInt8 Data;
+public:
+ PcxExpand() { Count=0; }
+ sal_uInt8 GetByte(SvStream& rInp);
+};
+
+sal_uInt8 PcxExpand::GetByte(SvStream& rInp)
+{
+ if (Count>0) {
+ Count--;
+ } else {
+ rInp.Read((char*)&Data,1);
+ if ((Data & 0xC0) == 0xC0) {
+ Count=(Data & 0x3F) -1;
+ rInp.Read((char*)&Data,1);
+ }
+ }
+ return Data;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// SgfBMapFilter ///////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+sal_Bool SgfFilterBMap(SvStream& rInp, SvStream& rOut, SgfHeader& rHead, SgfEntry&)
+{
+ BmpFileHeader aBmpHead;
+ BmpInfoHeader aBmpInfo;
+ sal_uInt16 nWdtInp=(rHead.Xsize+7)/8; // Breite der Input-Bitmap in Bytes
+ sal_uInt16 nWdtOut; // Breite der Output-Bitmap in Bytes
+ sal_uInt16 nColors; // Anzahl der Farben (1,16,256)
+ sal_uInt16 nColBits; // Anzahl der Bits/Pixel (2, 4, 8)
+ sal_uInt16 i,j,k; // Spaltenzaehler, Zeilenzaehler, Planezaehler
+ sal_uInt16 a,b; // Hilfsvariable
+ sal_uInt8 pl1 = 0; // Masken fuer die Planes
+ sal_uInt8* pBuf=NULL; // Buffer fuer eine Pixelzeile
+ PcxExpand aPcx;
+ sal_uLong nOfs;
+ sal_uInt8 cRGB[4];
+
+ if (rHead.Planes<=1) nColBits=1; else nColBits=4; if (rHead.Typ==4) nColBits=8;
+ nColors=1<<nColBits;
+ nWdtOut=((rHead.Xsize*nColBits+31)/32)*4;
+ aBmpHead.Typ='B'+'M'*256;
+ aBmpHead.SetOfs(sizeof(aBmpHead)+sizeof(aBmpInfo)+nColors*4);
+ aBmpHead.SetSize(aBmpHead.GetOfs()+nWdtOut*rHead.Ysize);
+ aBmpHead.Reserve1=0;
+ aBmpHead.Reserve2=0;
+ aBmpInfo.Size=sizeof(aBmpInfo);
+ aBmpInfo.Width=rHead.Xsize;
+ aBmpInfo.Hight=rHead.Ysize;
+ aBmpInfo.Planes=1;
+ aBmpInfo.PixBits=nColBits;
+ aBmpInfo.Compress=0;
+ aBmpInfo.ImgSize=0;
+ aBmpInfo.xDpmm=0;
+ aBmpInfo.yDpmm=0;
+ aBmpInfo.ColUsed=0;
+ aBmpInfo.ColMust=0;
+ pBuf=new sal_uInt8[nWdtOut];
+ if (!pBuf) return sal_False; // Fehler: kein Speichel da
+ rOut<<aBmpHead<<aBmpInfo;
+ memset(pBuf,0,nWdtOut); // Buffer mit Nullen fuellen
+
+ if (nColors==2)
+ {
+
+ rOut<<RGBQuad(0x00,0x00,0x00); // Schwarz
+ rOut<<RGBQuad(0xFF,0xFF,0xFF); // Weiss
+ nOfs=rOut.Tell();
+ for (j=0;j<rHead.Ysize;j++)
+ rOut.Write((char*)pBuf,nWdtOut); // Datei erstmal komplett mit Nullen fuellen
+ for (j=0;j<rHead.Ysize;j++) {
+ for(i=0;i<nWdtInp;i++) {
+ pBuf[i]=aPcx.GetByte(rInp);
+ }
+ for(i=nWdtInp;i<nWdtOut;i++) pBuf[i]=0; // noch bis zu 3 Bytes
+ rOut.Seek(nOfs+((sal_uLong)rHead.Ysize-j-1L)*(sal_uLong)nWdtOut); // rueckwaerts schreiben!
+ rOut.Write((char*)pBuf,nWdtOut);
+ }
+ } else if (nColors==16) {
+ sal_uInt8 pl2= 0; // Masken fuer die Planes
+
+ rOut<<RGBQuad(0x00,0x00,0x00); // Schwarz
+ rOut<<RGBQuad(0x24,0x24,0x24); // Grau 80%
+ rOut<<RGBQuad(0x49,0x49,0x49); // Grau 60%
+ rOut<<RGBQuad(0x92,0x92,0x92); // Grau 40%
+ rOut<<RGBQuad(0x6D,0x6D,0x6D); // Grau 30%
+ rOut<<RGBQuad(0xB6,0xB6,0xB6); // Grau 20%
+ rOut<<RGBQuad(0xDA,0xDA,0xDA); // Grau 10%
+ rOut<<RGBQuad(0xFF,0xFF,0xFF); // Weiss
+ rOut<<RGBQuad(0x00,0x00,0x00); // Schwarz
+ rOut<<RGBQuad(0xFF,0x00,0x00); // Rot
+ rOut<<RGBQuad(0x00,0x00,0xFF); // Blau
+ rOut<<RGBQuad(0xFF,0x00,0xFF); // Magenta
+ rOut<<RGBQuad(0x00,0xFF,0x00); // Gruen
+ rOut<<RGBQuad(0xFF,0xFF,0x00); // Gelb
+ rOut<<RGBQuad(0x00,0xFF,0xFF); // Cyan
+ rOut<<RGBQuad(0xFF,0xFF,0xFF); // Weiss
+
+ nOfs=rOut.Tell();
+ for (j=0;j<rHead.Ysize;j++)
+ rOut.Write((char*)pBuf,nWdtOut); // Datei erstmal komplett mit Nullen fuellen
+ for (j=0;j<rHead.Ysize;j++) {
+ memset(pBuf,0,nWdtOut);
+ for(k=0;k<4;k++) {
+ if (k==0) {
+ pl1=0x10; pl2=0x01;
+ } else {
+ pl1<<=1; pl2<<=1;
+ }
+ for(i=0;i<nWdtInp;i++) {
+ a=i*4;
+ b=aPcx.GetByte(rInp);
+ if (b & 0x80) pBuf[a ]|=pl1;
+ if (b & 0x40) pBuf[a ]|=pl2;
+ if (b & 0x20) pBuf[a+1]|=pl1;
+ if (b & 0x10) pBuf[a+1]|=pl2;
+ if (b & 0x08) pBuf[a+2]|=pl1;
+ if (b & 0x04) pBuf[a+2]|=pl2;
+ if (b & 0x02) pBuf[a+3]|=pl1;
+ if (b & 0x01) pBuf[a+3]|=pl2;
+ }
+ }
+ for(i=nWdtInp*4;i<nWdtOut;i++) pBuf[i]=0; // noch bis zu 3 Bytes
+ rOut.Seek(nOfs+((sal_uLong)rHead.Ysize-j-1L)*(sal_uLong)nWdtOut); // rueckwaerts schreiben!
+ rOut.Write((char*)pBuf,nWdtOut);
+ }
+ } else if (nColors==256) {
+ cRGB[3]=0; // der 4. Paletteneintrag fuer BMP
+ for (i=0;i<256;i++) { // Palette kopieren
+ rInp.Read((char*)cRGB,3);
+ pl1=cRGB[0]; // Rot mit Blau tauschen
+ cRGB[0]=cRGB[2];
+ cRGB[2]=pl1;
+ rOut.Write((char*)cRGB,4);
+ }
+
+ nOfs=rOut.Tell();
+ for (j=0;j<rHead.Ysize;j++)
+ rOut.Write((char*)pBuf,nWdtOut); // Datei erstmal komplett mit Nullen fuellen
+ for (j=0;j<rHead.Ysize;j++) {
+ for(i=0;i<rHead.Xsize;i++)
+ pBuf[i]=aPcx.GetByte(rInp);
+ for(i=rHead.Xsize;i<nWdtOut;i++) pBuf[i]=0; // noch bis zu 3 Bytes
+ rOut.Seek(nOfs+((sal_uLong)rHead.Ysize-j-1L)*(sal_uLong)nWdtOut); // rueckwaerts schreiben!
+ rOut.Write((char*)pBuf,nWdtOut);
+ }
+ }
+ delete[] pBuf;
+ return sal_True;
+}
+
+sal_Bool SgfBMapFilter(SvStream& rInp, SvStream& rOut)
+{
+ sal_uLong nFileStart; // Offset des SgfHeaders. Im allgemeinen 0.
+ SgfHeader aHead;
+ SgfEntry aEntr;
+ sal_uLong nNext;
+ sal_Bool bRdFlag=sal_False; // Grafikentry gelesen ?
+ sal_Bool bRet=sal_False; // Returncode
+
+ nFileStart=rInp.Tell();
+ rInp>>aHead;
+ if (aHead.ChkMagic() && (aHead.Typ==SgfBitImag0 || aHead.Typ==SgfBitImag1 ||
+ aHead.Typ==SgfBitImag2 || aHead.Typ==SgfBitImgMo)) {
+ nNext=aHead.GetOffset();
+ while (nNext && !bRdFlag && !rInp.GetError() && !rOut.GetError()) {
+ rInp.Seek(nFileStart+nNext);
+ rInp>>aEntr;
+ nNext=aEntr.GetOffset();
+ if (aEntr.Typ==aHead.Typ) {
+ bRdFlag=sal_True;
+ switch(aEntr.Typ) {
+ case SgfBitImag0:
+ case SgfBitImag1:
+ case SgfBitImag2:
+ case SgfBitImgMo: bRet=SgfFilterBMap(rInp,rOut,aHead,aEntr); break;
+ }
+ }
+ } // while(nNext)
+ }
+ if (rInp.GetError()) bRet=sal_False;
+ return(bRet);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// SgfVectFilter ///////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// Fuer StarDraw Embedded SGF-Vector
+long SgfVectXofs=0;
+long SgfVectYofs=0;
+long SgfVectXmul=0;
+long SgfVectYmul=0;
+long SgfVectXdiv=0;
+long SgfVectYdiv=0;
+sal_Bool SgfVectScal=sal_False;
+
+////////////////////////////////////////////////////////////
+// Hpgl2SvFarbe ////////////////////////////////////////////
+////////////////////////////////////////////////////////////
+
+Color Hpgl2SvFarbe( sal_uInt8 nFarb )
+{
+ sal_uLong nColor = COL_BLACK;
+
+ switch (nFarb & 0x07) {
+ case 0: nColor=COL_WHITE; break;
+ case 1: nColor=COL_YELLOW; break;
+ case 2: nColor=COL_LIGHTMAGENTA; break;
+ case 3: nColor=COL_LIGHTRED; break;
+ case 4: nColor=COL_LIGHTCYAN; break;
+ case 5: nColor=COL_LIGHTGREEN; break;
+ case 6: nColor=COL_LIGHTBLUE; break;
+ case 7: nColor=COL_BLACK; break;
+ }
+ Color aColor( nColor );
+ return aColor;
+}
+
+sal_Bool SgfFilterVect(SvStream& rInp, SgfHeader& rHead, SgfEntry&, GDIMetaFile& rMtf)
+{
+ VirtualDevice aOutDev;
+ SgfVector aVect;
+ sal_uInt8 nFarb;
+ sal_uInt8 nFrb0=7;
+ sal_uInt8 nLTyp;
+ sal_uInt8 nOTyp;
+ sal_Bool bEoDt=sal_False;
+ sal_Bool bPDwn=sal_False;
+ Point aP0(0,0);
+ Point aP1(0,0);
+ String Msg;
+ sal_uInt16 RecNr=0;
+
+ rMtf.Record(&aOutDev);
+ aOutDev.SetLineColor(Color(COL_BLACK));
+ aOutDev.SetFillColor(Color(COL_BLACK));
+
+ while (!bEoDt && !rInp.GetError()) {
+ rInp>>aVect; RecNr++;
+ nFarb=(sal_uInt8) (aVect.Flag & 0x000F);
+ nLTyp=(sal_uInt8)((aVect.Flag & 0x00F0) >>4);
+ nOTyp=(sal_uInt8)((aVect.Flag & 0x0F00) >>8);
+ bEoDt=(aVect.Flag & 0x4000) !=0;
+ bPDwn=(aVect.Flag & 0x8000) !=0;
+
+ long x=aVect.x-rHead.Xoffs;
+ long y=rHead.Ysize-(aVect.y-rHead.Yoffs);
+ if (SgfVectScal) {
+ if (SgfVectXdiv==0) SgfVectXdiv=rHead.Xsize;
+ if (SgfVectYdiv==0) SgfVectYdiv=rHead.Ysize;
+ if (SgfVectXdiv==0) SgfVectXdiv=1;
+ if (SgfVectYdiv==0) SgfVectYdiv=1;
+ x=SgfVectXofs+ x *SgfVectXmul /SgfVectXdiv;
+ y=SgfVectYofs+ y *SgfVectXmul /SgfVectYdiv;
+ }
+ aP1=Point(x,y);
+ if (!bEoDt && !rInp.GetError()) {
+ if (bPDwn && nLTyp<=6) {
+ switch(nOTyp) {
+ case 1: if (nFarb!=nFrb0) {
+ switch(rHead.SwGrCol) {
+ case SgfVectFarb: aOutDev.SetLineColor(Hpgl2SvFarbe(nFarb)); break;
+ case SgfVectGray: break;
+ case SgfVectWdth: break;
+ }
+ }
+ aOutDev.DrawLine(aP0,aP1); break; // Linie
+ case 2: break; // Kreis
+ case 3: break; // Text
+ case 5: aOutDev.DrawRect(Rectangle(aP0,aP1)); break; // Rechteck (solid)
+ }
+ }
+ aP0=aP1;
+ nFrb0=nFarb;
+ }
+ }
+ rMtf.Stop();
+ rMtf.WindStart();
+ MapMode aMap( MAP_10TH_MM, Point(),
+ Fraction( 1, 4 ), Fraction( 1, 4 ) );
+ rMtf.SetPrefMapMode( aMap );
+ rMtf.SetPrefSize( Size( (short)rHead.Xsize, (short)rHead.Ysize ) );
+ return sal_True;
+}
+
+
+sal_Bool SgfVectFilter(SvStream& rInp, GDIMetaFile& rMtf)
+{
+ sal_uLong nFileStart; // Offset des SgfHeaders. Im allgemeinen 0.
+ SgfHeader aHead;
+ SgfEntry aEntr;
+ sal_uLong nNext;
+ sal_Bool bRdFlag=sal_False; // Grafikentry gelesen ?
+ sal_Bool bRet=sal_False; // Returncode
+
+ nFileStart=rInp.Tell();
+ rInp>>aHead;
+ if (aHead.ChkMagic() && aHead.Typ==SGF_SIMPVECT) {
+ nNext=aHead.GetOffset();
+ while (nNext && !bRdFlag && !rInp.GetError()) {
+ rInp.Seek(nFileStart+nNext);
+ rInp>>aEntr;
+ nNext=aEntr.GetOffset();
+ if (aEntr.Typ==aHead.Typ) {
+ bRet=SgfFilterVect(rInp,aHead,aEntr,rMtf);
+ }
+ } // while(nNext)
+ if (bRdFlag) {
+ if (!rInp.GetError()) bRet=sal_True; // Scheinbar Ok
+ }
+ }
+ return(bRet);
+}
+
+/*************************************************************************
+|*
+|* CheckSgfTyp()
+|*
+|* Beschreibung Feststellen, um was fuer ein SGF/SGV es sich handelt.
+|*
+*************************************************************************/
+sal_uInt8 CheckSgfTyp(SvStream& rInp, sal_uInt16& nVersion)
+{
+#if OSL_DEBUG_LEVEL > 1 // Recordgroessen checken. Neuer Compiler hat vielleichte anderes Allignment!
+ if (sizeof(SgfHeader)!=SgfHeaderSize ||
+ sizeof(SgfEntry) !=SgfEntrySize ||
+ sizeof(SgfVector)!=SgfVectorSize ||
+ sizeof(BmpFileHeader)!=BmpFileHeaderSize ||
+ sizeof(BmpInfoHeader)!=BmpInfoHeaderSize ||
+ sizeof(RGBQuad )!=RGBQuadSize ) return SGF_DONTKNOW;
+#endif
+
+ sal_uLong nPos;
+ SgfHeader aHead;
+ nVersion=0;
+ nPos=rInp.Tell();
+ rInp>>aHead;
+ rInp.Seek(nPos);
+ if (aHead.ChkMagic()) {
+ nVersion=aHead.Version;
+ switch(aHead.Typ) {
+ case SgfBitImag0:
+ case SgfBitImag1:
+ case SgfBitImag2:
+ case SgfBitImgMo: return SGF_BITIMAGE;
+ case SgfSimpVect: return SGF_SIMPVECT;
+ case SgfPostScrp: return SGF_POSTSCRP;
+ case SgfStarDraw: return SGF_STARDRAW;
+ default : return SGF_DONTKNOW;
+ }
+ } else {
+ return SGF_DONTKNOW;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgfbram.hxx b/vcl/source/filter/sgfbram.hxx
new file mode 100644
index 000000000000..ad7231c2911b
--- /dev/null
+++ b/vcl/source/filter/sgfbram.hxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _SGFBRAM_HXX
+#define _SGFBRAM_HXX
+
+#include <tools/solar.h>
+
+#define SgfBitImag0 1 /* Bitmap */
+#define SgfBitImag1 4 /* Bitmap */
+#define SgfBitImag2 5 /* Bitmap */
+#define SgfBitImgMo 6 /* Monochrome Bitmap */
+#define SgfSimpVect 2 /* Einfaches Vectorformat */
+#define SgfPostScrp 3 /* Postscript file */
+#define SgfStarDraw 7 /* StarDraw SGV-Datei */
+#define SgfDontKnow 255 /* Unbekannt oder kein SGF/SGV */
+
+// Konstanten fr SgfHeader.SwGrCol
+#define SgfBlckWhit 1 /* Schwarz/Wei?Bild Ä¿ SimpVector, */
+#define SgfGrayscal 2 /* Bild mit Graustufen ?StarDraw und */
+#define Sgf16Colors 3 /* Farbbild (16 Farben) ÄÙ Bit Image */
+#define SgfVectFarb 4 /* Farben fr Linien verwenden Ä¿ */
+#define SgfVectGray 5 /* Graustufen fr Linien verwenden ?Nur fr */
+#define SgfVectWdth 6 /* Strichst„rken fr Linien verwenden ÄÙ SimpVector */
+
+
+#define SgfHeaderSize 42
+class SgfHeader
+{
+public:
+ sal_uInt16 Magic;
+ sal_uInt16 Version;
+ sal_uInt16 Typ;
+ sal_uInt16 Xsize;
+ sal_uInt16 Ysize;
+ sal_Int16 Xoffs;
+ sal_Int16 Yoffs;
+ sal_uInt16 Planes; // Layer
+ sal_uInt16 SwGrCol;
+ char Autor[10];
+ char Programm[10];
+ sal_uInt16 OfsLo,OfsHi; // DWord-Allignment ist notwendig (38 mod 4 =2) !
+
+ sal_uInt32 GetOffset();
+ friend SvStream& operator>>(SvStream& rIStream, SgfHeader& rHead);
+ sal_Bool ChkMagic();
+};
+
+#define SgfEntrySize 22
+class SgfEntry
+{
+public:
+ sal_uInt16 Typ;
+ sal_uInt16 iFrei;
+ sal_uInt16 lFreiLo,lFreiHi;
+ char cFrei[10];
+ sal_uInt16 OfsLo,OfsHi; // DWord-Allignment ist notwendig (18 mod 4 =2) !
+
+ sal_uInt32 GetOffset();
+ friend SvStream& operator>>(SvStream& rIStream, SgfEntry& rEntr);
+};
+
+#define SgfVectorSize 10
+class SgfVector
+{
+public:
+ sal_uInt16 Flag;
+ sal_Int16 x;
+ sal_Int16 y;
+ sal_uInt16 OfsLo,OfsHi; // DWord-Allignment ist notwendig (6 mod 4 =2) !
+
+ friend SvStream& operator>>(SvStream& rIStream, SgfVector& rEntr);
+};
+
+extern long SgfVectXofs;
+extern long SgfVectYofs;
+extern long SgfVectXmul;
+extern long SgfVectYmul;
+extern long SgfVectXdiv;
+extern long SgfVectYdiv;
+extern sal_Bool SgfVectScal;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Windows BMP /////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define BmpFileHeaderSize 14
+class BmpFileHeader
+{
+public:
+ sal_uInt16 Typ; // = "BM"
+ sal_uInt16 SizeLo,SizeHi; // Filesize in Bytes
+ sal_uInt16 Reserve1; // Reserviert
+ sal_uInt16 Reserve2; // Reserviert
+ sal_uInt16 OfsLo,OfsHi; // Offset?
+
+ void SetSize(sal_uInt32 Size);
+ void SetOfs(sal_uInt32 Size);
+ sal_uInt32 GetOfs();
+ friend SvStream& operator<<(SvStream& rOStream, BmpFileHeader& rHead);
+};
+
+#define BmpInfoHeaderSize 40
+class BmpInfoHeader
+{
+public:
+ sal_uInt32 Size; // GrӇe des BmpInfoHeaders
+ sal_Int32 Width; // Breite in Pixel
+ sal_Int32 Hight; // H”he in Pixel
+ sal_uInt16 Planes; // Anzahl der Planes (immer 1)
+ sal_uInt16 PixBits; // Anzahl der Bit je Pixel (1,4,8,oder 24)
+ sal_uInt32 Compress; // Datenkompression
+ sal_uInt32 ImgSize; // GrӇe der Images in Bytes. Ohne Kompression ist auch 0 erlaubt.
+ sal_Int32 xDpmm; // Dot per Meter (0 ist erlaubt)
+ sal_Int32 yDpmm; // Dot per Meter (0 ist erlaubt)
+ sal_uInt32 ColUsed; // Anzahl der verwendeten Farben (0=alle)
+ sal_uInt32 ColMust; // Anzahl der wichtigen Farben (0=alle)
+
+ friend SvStream& operator<<(SvStream& rOStream, BmpInfoHeader& rHead);
+};
+
+#define RGBQuadSize 4
+class RGBQuad {
+private:
+ sal_uInt8 Red;
+ sal_uInt8 Grn;
+ sal_uInt8 Blu;
+ sal_uInt8 Fil;
+public:
+ RGBQuad(sal_uInt8 R, sal_uInt8 G, sal_uInt8 B) { Red=R; Grn=G; Blu=B; Fil=0; }
+};
+
+#endif //_SGFBRAM_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgffilt.hxx b/vcl/source/filter/sgffilt.hxx
new file mode 100644
index 000000000000..9d19dbbc42ad
--- /dev/null
+++ b/vcl/source/filter/sgffilt.hxx
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _SGFFILT_HXX
+#define _SGFFILT_HXX
+#include <tools/urlobj.hxx>
+
+sal_uInt8 CheckSgfTyp(SvStream& rInp, sal_uInt16& nVersion);
+sal_Bool SgfBMapFilter(SvStream& rInp, SvStream& rOut);
+sal_Bool SgfVectFilter(SvStream& rInp, GDIMetaFile& rMtf);
+sal_Bool SgfSDrwFilter(SvStream& rInp, GDIMetaFile& rMtf, INetURLObject aIniPath );
+
+// Konstanten fr CheckSgfTyp()
+#define SGF_BITIMAGE 1 /* Bitmap */
+#define SGF_SIMPVECT 2 /* Einfaches Vectorformat */
+#define SGF_POSTSCRP 3 /* Postscript file */
+#define SGF_STARDRAW 7 /* StarDraw SGV-Datei */
+#define SGF_DONTKNOW 255 /* Unbekannt oder kein SGF/SGV */
+
+#define SGV_VERSION 3 /* SGV mit anderer Version wird abgewiesen */
+ /* 3 entspricht StarDraw 2.00/2.01 M„rz'93 */
+#endif //_SGFFILT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgvmain.cxx b/vcl/source/filter/sgvmain.cxx
new file mode 100644
index 000000000000..667856464164
--- /dev/null
+++ b/vcl/source/filter/sgvmain.cxx
@@ -0,0 +1,966 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <rtl/math.hxx>
+#include <osl/endian.h>
+#include <vcl/graph.hxx>
+#include <tools/poly.hxx>
+#include <svtools/filter.hxx>
+#include "sgffilt.hxx"
+#include "sgfbram.hxx"
+#include "sgvmain.hxx"
+#include "sgvspln.hxx"
+#include <unotools/ucbstreamhelper.hxx>
+
+#define SWAPPOINT(p) { \
+ p.x=OSL_SWAPWORD(p.x); \
+ p.y=OSL_SWAPWORD(p.y); }
+
+#define SWAPPAGE(p) { \
+ p.Next =OSL_SWAPDWORD (p.Next ); \
+ p.nList =OSL_SWAPDWORD (p.nList ); \
+ p.ListEnd=OSL_SWAPDWORD (p.ListEnd); \
+ p.Paper.Size.x=OSL_SWAPWORD(p.Paper.Size.x); \
+ p.Paper.Size.y=OSL_SWAPWORD(p.Paper.Size.y); \
+ p.Paper.RandL =OSL_SWAPWORD(p.Paper.RandL ); \
+ p.Paper.RandR =OSL_SWAPWORD(p.Paper.RandR ); \
+ p.Paper.RandO =OSL_SWAPWORD(p.Paper.RandO ); \
+ p.Paper.RandU =OSL_SWAPWORD(p.Paper.RandU ); \
+ SWAPPOINT(p.U); \
+ sal_uInt16 iTemp; \
+ for (iTemp=0;iTemp<20;iTemp++) { \
+ rPage.HlpLnH[iTemp]=OSL_SWAPWORD(rPage.HlpLnH[iTemp]); \
+ rPage.HlpLnV[iTemp]=OSL_SWAPWORD(rPage.HlpLnV[iTemp]); }}
+
+#define SWAPOBJK(o) { \
+ o.Last =OSL_SWAPDWORD (o.Last ); \
+ o.Next =OSL_SWAPDWORD (o.Next ); \
+ o.MemSize =OSL_SWAPWORD(o.MemSize ); \
+ SWAPPOINT(o.ObjMin); \
+ SWAPPOINT(o.ObjMax); }
+
+#define SWAPLINE(l) { \
+ l.LMSize=OSL_SWAPWORD(l.LMSize); \
+ l.LDicke=OSL_SWAPWORD(l.LDicke); }
+
+#define SWAPAREA(a) { \
+ a.FDummy2=OSL_SWAPWORD(a.FDummy2); \
+ a.FMuster=OSL_SWAPWORD(a.FMuster); }
+
+#define SWAPTEXT(t) { \
+ SWAPLINE(t.L); \
+ SWAPAREA(t.F); \
+ t.FontLo =OSL_SWAPWORD(t.FontLo ); \
+ t.FontHi =OSL_SWAPWORD(t.FontHi ); \
+ t.Grad =OSL_SWAPWORD(t.Grad ); \
+ t.Breite =OSL_SWAPWORD(t.Breite ); \
+ t.Schnitt=OSL_SWAPWORD(t.Schnitt); \
+ t.LnFeed =OSL_SWAPWORD(t.LnFeed ); \
+ t.Slant =OSL_SWAPWORD(t.Slant ); \
+ SWAPLINE(t.ShdL); \
+ SWAPAREA(t.ShdF); \
+ SWAPPOINT(t.ShdVers); \
+ SWAPAREA(t.BackF); }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Einschraenkungen:
+//
+// - Flaechenmuster werden den unter StarView verfuegbaren Mustern angenaehert.
+// - Linienenden werden unter StarView immer rund dargestellt und gehen ueber
+// den Endpunkt der Linie hinaus.
+// - Linienmuster werden den unter StarView verfuegbaren Mustern angenaehert.
+// Transparent/Opak wird zur Zeit noch nicht beruecksichtigt.
+// - Keine gedrehten Ellipsen
+//
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Fuer Fontuebersetzung ///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+SgfFontLst* pSgfFonts = 0;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Fuer Kreisunterarten, Text und gedrehte Rechtecke ///////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+void RotatePoint(PointType& P, sal_Int16 cx, sal_Int16 cy, double sn, double cs)
+{
+ sal_Int16 dx,dy;
+ double x1,y1;
+ dx=P.x-cx;
+ dy=P.y-cy;
+ x1=dx*cs-dy*sn;
+ y1=dy*cs+dx*sn;
+ P.x=cx+sal_Int16(x1);
+ P.y=cy+sal_Int16(y1);
+}
+
+void RotatePoint(Point& P, sal_Int16 cx, sal_Int16 cy, double sn, double cs)
+{
+ sal_Int16 dx,dy;
+ double x1,y1;
+ dx=(sal_Int16)(P.X()-cx);
+ dy=(sal_Int16)(P.Y()-cy);
+ x1=dx*cs-dy*sn;
+ y1=dy*cs+dx*sn;
+ P=Point(cx+sal_Int16(x1),cy+sal_Int16(y1));
+}
+
+sal_Int16 iMulDiv(sal_Int16 a, sal_Int16 Mul, sal_Int16 Div)
+{
+ sal_Int32 Temp;
+ Temp=sal_Int32(a)*sal_Int32(Mul)/sal_Int32(Div);
+ return sal_Int16(Temp);
+}
+
+sal_uInt16 MulDiv(sal_uInt16 a, sal_uInt16 Mul, sal_uInt16 Div)
+{
+ sal_uInt32 Temp;
+ Temp=sal_uInt32(a)*sal_uInt32(Mul)/sal_uInt32(Div);
+ return sal_uInt16(Temp);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// SgfFilterSDrw ///////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+SvStream& operator>>(SvStream& rIStream, DtHdType& rDtHd)
+{
+ rIStream.Read((char*)&rDtHd.Reserved[0],DtHdSize);
+ return rIStream;
+}
+
+void DtHdOverSeek(SvStream& rInp)
+{
+ sal_uLong FPos=rInp.Tell();
+ FPos+=(sal_uLong)DtHdSize;
+ rInp.Seek(FPos);
+}
+
+
+SvStream& operator>>(SvStream& rIStream, PageType& rPage)
+{
+ rIStream.Read((char*)&rPage.Next,PageSize);
+#if defined OSL_BIGENDIAN
+ SWAPPAGE(rPage);
+#endif
+ return rIStream;
+}
+
+void ObjkOverSeek(SvStream& rInp, ObjkType& rObjk)
+{
+ sal_uLong Siz;
+ Siz=(sal_uLong)rObjk.MemSize+rObjk.Last; // ObjSize+ObjAnhSize
+ rInp.Seek(rInp.Tell()+Siz);
+}
+
+SvStream& operator>>(SvStream& rInp, ObjkType& rObjk)
+{ // Die Fileposition im Stream bleibt unveraendert!
+ sal_uLong nPos;
+ nPos=rInp.Tell();
+ rInp.Read((char*)&rObjk.Last,ObjkSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK(rObjk);
+#endif
+#ifdef InArbeit
+ sal_uLong nPos1=rInp.Tell();
+ if(nPos == nPos1) InfoBox( NULL, "tellg funkt nich" ).Execute();
+#endif
+ rInp.Seek(nPos);
+#ifdef InArbeit
+ if (rInp.Tell() != nPos) InfoBox( NULL, "seekg funkt nich" ).Execute();
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, StrkType& rStrk)
+{
+ rInp.Read((char*)&rStrk.Last,StrkSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rStrk);
+ SWAPLINE (rStrk.L);
+ SWAPPOINT(rStrk.Pos1);
+ SWAPPOINT(rStrk.Pos2);
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, RectType& rRect)
+{
+ rInp.Read((char*)&rRect.Last,RectSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rRect);
+ SWAPLINE (rRect.L);
+ SWAPAREA (rRect.F);
+ SWAPPOINT(rRect.Pos1);
+ SWAPPOINT(rRect.Pos2);
+ rRect.Radius =OSL_SWAPWORD(rRect.Radius );
+ rRect.DrehWink=OSL_SWAPWORD(rRect.DrehWink);
+ rRect.Slant =OSL_SWAPWORD(rRect.Slant );
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, PolyType& rPoly)
+{
+ rInp.Read((char*)&rPoly.Last,PolySize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rPoly);
+ SWAPLINE (rPoly.L);
+ SWAPAREA (rPoly.F);
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, SplnType& rSpln)
+{
+ rInp.Read((char*)&rSpln.Last,SplnSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rSpln);
+ SWAPLINE (rSpln.L);
+ SWAPAREA (rSpln.F);
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, CircType& rCirc)
+{
+ rInp.Read((char*)&rCirc.Last,CircSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rCirc);
+ SWAPLINE (rCirc.L);
+ SWAPAREA (rCirc.F);
+ SWAPPOINT(rCirc.Radius);
+ SWAPPOINT(rCirc.Center);
+ rCirc.DrehWink =OSL_SWAPWORD(rCirc.DrehWink );
+ rCirc.StartWink=OSL_SWAPWORD(rCirc.StartWink);
+ rCirc.RelWink =OSL_SWAPWORD(rCirc.RelWink );
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, TextType& rText)
+{
+ rInp.Read((char*)&rText.Last,TextSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rText);
+ SWAPTEXT (rText.T);
+ SWAPPOINT(rText.Pos1);
+ SWAPPOINT(rText.Pos2);
+ rText.TopOfs =OSL_SWAPWORD(rText.TopOfs );
+ rText.DrehWink=OSL_SWAPWORD(rText.DrehWink);
+ rText.BoxSlant=OSL_SWAPWORD(rText.BoxSlant);
+ rText.BufSize =OSL_SWAPWORD(rText.BufSize );
+ SWAPPOINT(rText.FitSize);
+ rText.FitBreit=OSL_SWAPWORD(rText.FitBreit);
+#endif
+ rText.Buffer=NULL;
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, BmapType& rBmap)
+{
+ rInp.Read((char*)&rBmap.Last,BmapSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rBmap);
+ SWAPAREA (rBmap.F);
+ SWAPPOINT(rBmap.Pos1);
+ SWAPPOINT(rBmap.Pos2);
+ rBmap.DrehWink=OSL_SWAPWORD(rBmap.DrehWink);
+ rBmap.Slant =OSL_SWAPWORD(rBmap.Slant );
+ SWAPPOINT(rBmap.PixSize);
+#endif
+ return rInp;
+}
+SvStream& operator>>(SvStream& rInp, GrupType& rGrup)
+{
+ rInp.Read((char*)&rGrup.Last,GrupSize);
+#if defined OSL_BIGENDIAN
+ SWAPOBJK (rGrup);
+ rGrup.SbLo =OSL_SWAPWORD(rGrup.SbLo );
+ rGrup.SbHi =OSL_SWAPWORD(rGrup.SbHi );
+ rGrup.UpLo =OSL_SWAPWORD(rGrup.UpLo );
+ rGrup.UpHi =OSL_SWAPWORD(rGrup.UpHi );
+ rGrup.ChartSize=OSL_SWAPWORD(rGrup.ChartSize);
+ rGrup.ChartPtr =OSL_SWAPDWORD (rGrup.ChartPtr );
+#endif
+ return rInp;
+}
+
+
+
+/*************************************************************************
+|*
+|* Sgv2SvFarbe()
+|*
+*************************************************************************/
+Color Sgv2SvFarbe(sal_uInt8 nFrb1, sal_uInt8 nFrb2, sal_uInt8 nInts)
+{
+ sal_uInt16 r1=0,g1=0,b1=0,r2=0,g2=0,b2=0;
+ sal_uInt8 nInt2=100-nInts;
+ switch(nFrb1 & 0x07) {
+ case 0: r1=0xFF; g1=0xFF; b1=0xFF; break;
+ case 1: r1=0xFF; g1=0xFF; break;
+ case 2: g1=0xFF; b1=0xFF; break;
+ case 3: g1=0xFF; break;
+ case 4: r1=0xFF; b1=0xFF; break;
+ case 5: r1=0xFF; break;
+ case 6: b1=0xFF; break;
+ case 7: break;
+ }
+ switch(nFrb2 & 0x07) {
+ case 0: r2=0xFF; g2=0xFF; b2=0xFF; break;
+ case 1: r2=0xFF; g2=0xFF; break;
+ case 2: g2=0xFF; b2=0xFF; break;
+ case 3: g2=0xFF; break;
+ case 4: r2=0xFF; b2=0xFF; break;
+ case 5: r2=0xFF; break;
+ case 6: b2=0xFF; break;
+ case 7: break;
+ }
+ r1=(sal_uInt16)((sal_uInt32)r1*nInts/100+(sal_uInt32)r2*nInt2/100);
+ g1=(sal_uInt16)((sal_uInt32)g1*nInts/100+(sal_uInt32)g2*nInt2/100);
+ b1=(sal_uInt16)((sal_uInt32)b1*nInts/100+(sal_uInt32)b2*nInt2/100);
+ Color aColor( (sal_uInt8)r1, (sal_uInt8)g1, (sal_uInt8)b1 );
+ return aColor;
+}
+
+void SetLine(ObjLineType& rLine, OutputDevice& rOut)
+{
+ if( 0 == ( rLine.LMuster & 0x07 ) )
+ rOut.SetLineColor();
+ else
+ rOut.SetLineColor( Sgv2SvFarbe(rLine.LFarbe,rLine.LBFarbe,rLine.LIntens) );
+}
+
+void SetArea(ObjAreaType& rArea, OutputDevice& rOut)
+{
+ if( 0 == ( rArea.FMuster & 0x00FF ) )
+ rOut.SetFillColor();
+ else
+ rOut.SetFillColor( Sgv2SvFarbe( rArea.FFarbe,rArea.FBFarbe,rArea.FIntens ) );
+}
+
+/*************************************************************************
+|*
+|* ObjkType::DrawObjekt()
+|*
+*************************************************************************/
+void ObjkType::Draw(OutputDevice&)
+{
+}
+
+void Obj0Type::Draw(OutputDevice&) {}
+
+/*************************************************************************
+|*
+|* StrkType::DrawObjekt()
+|*
+*************************************************************************/
+void StrkType::Draw(OutputDevice& rOut)
+{
+ SetLine(L,rOut);
+ rOut.DrawLine(Point(Pos1.x,Pos1.y),Point(Pos2.x,Pos2.y)); // !!!
+}
+
+/*************************************************************************
+|*
+|* RectType::DrawObjekt()
+|*
+*************************************************************************/
+void SgfAreaColorIntens(sal_uInt16 Muster, sal_uInt8 Col1, sal_uInt8 Col2, sal_uInt8 Int, OutputDevice& rOut)
+{
+ ObjAreaType F;
+ F.FMuster=Muster;
+ F.FFarbe=Col2;
+ F.FBFarbe=Col1;
+ F.FIntens=Int;
+ SetArea(F,rOut);
+}
+
+void DrawSlideRect(sal_Int16 x1, sal_Int16 y1, sal_Int16 x2, sal_Int16 y2, ObjAreaType& F, OutputDevice& rOut)
+{
+ sal_Int16 i,i0,b,b0;
+ sal_Int16 Int1,Int2;
+ sal_Int16 Col1,Col2;
+ // ClipMerk: HgdClipRec;
+ sal_Int16 cx,cy;
+ sal_Int16 MaxR;
+ sal_Int32 dx,dy;
+
+ rOut.SetLineColor();
+ if (x1>x2) { i=x1; x1=x2; x2=i; }
+ if (y1>y2) { i=y1; y1=y2; y2=i; }
+ Col1=F.FBFarbe & 0x87; Col2=F.FFarbe & 0x87;
+ Int1=100-F.FIntens; Int2=F.FIntens;
+ if (Int1==Int2) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.DrawRect(Rectangle(x1,y1,x2,y2));
+ } else {
+ b0=Int1;
+ switch (F.FBFarbe & 0x38) {
+ case 0x08: { // vertikal
+ i0=y1;
+ i=y1;
+ while (i<=y2) {
+ b=Int1+sal_Int16((sal_Int32)(Int2-Int1)*(sal_Int32)(i-y1) /(sal_Int32)(y2-y1+1));
+ if (b!=b0) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.DrawRect(Rectangle(x1,i0,x2,i-1));
+ i0=i; b0=b;
+ }
+ i++;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.DrawRect(Rectangle(x1,i0,x2,y2));
+ } break;
+ case 0x28: { // horizontal
+ i0=x1;
+ i=x1;
+ while (i<=x2) {
+ b=Int1+sal_Int16((sal_Int32)(Int2-Int1)*(sal_Int32)(i-x1) /(sal_Int32)(x2-x1+1));
+ if (b!=b0) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.DrawRect(Rectangle(i0,y1,i-1,y2));
+ i0=i; b0=b;
+ }
+ i++;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.DrawRect(Rectangle(i0,y1,x2,y2));
+ } break;
+
+ case 0x18: case 0x38: { // Kreis
+ Region ClipMerk=rOut.GetClipRegion();
+ double a;
+
+ rOut.SetClipRegion(Region(Rectangle(x1,y1,x2,y2)));
+ cx=(x1+x2) /2;
+ cy=(y1+y2) /2;
+ dx=x2-x1+1;
+ dy=y2-y1+1;
+ a=sqrt((double)(dx*dx+dy*dy));
+ MaxR=sal_Int16(a) /2 +1;
+ b0=Int2;
+ i0=MaxR; if (MaxR<1) MaxR=1;
+ i=MaxR;
+ while (i>=0) {
+ b=Int1+sal_Int16((sal_Int32(Int2-Int1)*sal_Int32(i)) /sal_Int32(MaxR));
+ if (b!=b0) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.DrawEllipse(Rectangle(cx-i0,cy-i0,cx+i0,cy+i0));
+ i0=i; b0=b;
+ }
+ i--;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int1,rOut);
+ rOut.DrawEllipse(Rectangle(cx-i0,cy-i0,cx+i0,cy+i0));
+ rOut.SetClipRegion(ClipMerk);
+ } break; // Kreis
+ }
+ }
+}
+
+
+void RectType::Draw(OutputDevice& rOut)
+{
+ if (L.LMuster!=0) L.LMuster=1; // keine Linienmuster hier, nur an oder aus
+ SetArea(F,rOut);
+ if (DrehWink==0) {
+ if ((F.FBFarbe & 0x38)==0 || Radius!=0) {
+ SetLine(L,rOut);
+ rOut.DrawRect(Rectangle(Pos1.x,Pos1.y,Pos2.x,Pos2.y),Radius,Radius);
+ } else {
+ DrawSlideRect(Pos1.x,Pos1.y,Pos2.x,Pos2.y,F,rOut);
+ if (L.LMuster!=0) {
+ SetLine(L,rOut);
+ rOut.SetFillColor();
+ rOut.DrawRect(Rectangle(Pos1.x,Pos1.y,Pos2.x,Pos2.y));
+ }
+ }
+ } else {
+ Point aPts[4];
+ sal_uInt16 i;
+ double sn,cs;
+ sn=sin(double(DrehWink)*3.14159265359/18000);
+ cs=cos(double(DrehWink)*3.14159265359/18000);
+ aPts[0]=Point(Pos1.x,Pos1.y);
+ aPts[1]=Point(Pos2.x,Pos1.y);
+ aPts[2]=Point(Pos2.x,Pos2.y);
+ aPts[3]=Point(Pos1.x,Pos2.y);
+ for (i=0;i<4;i++) {
+ RotatePoint(aPts[i],Pos1.x,Pos1.y,sn,cs);
+ }
+ SetLine(L,rOut);
+ Polygon aPoly(4,aPts);
+ rOut.DrawPolygon(aPoly);
+ }
+}
+
+/*************************************************************************
+|*
+|* PolyType::Draw()
+|*
+*************************************************************************/
+void PolyType::Draw(OutputDevice& rOut)
+{
+ if ((Flags & PolyClosBit) !=0) SetArea(F,rOut);
+ SetLine(L,rOut);
+ Polygon aPoly(nPoints);
+ sal_uInt16 i;
+ for(i=0;i<nPoints;i++) aPoly.SetPoint(Point(EckP[i].x,EckP[i].y),i);
+ if ((Flags & PolyClosBit) !=0) {
+ rOut.DrawPolygon(aPoly);
+ } else {
+ rOut.DrawPolyLine(aPoly);
+ }
+}
+
+/*************************************************************************
+|*
+|* SplnType::Draw()
+|*
+*************************************************************************/
+void SplnType::Draw(OutputDevice& rOut)
+{
+ if ((Flags & PolyClosBit) !=0) SetArea(F,rOut);
+ SetLine(L,rOut);
+ Polygon aPoly(0);
+ Polygon aSpln(nPoints);
+ sal_uInt16 i;
+ for(i=0;i<nPoints;i++) aSpln.SetPoint(Point(EckP[i].x,EckP[i].y),i);
+ if ((Flags & PolyClosBit) !=0) {
+ Spline2Poly(aSpln,sal_True,aPoly);
+ if (aPoly.GetSize()>0) rOut.DrawPolygon(aPoly);
+ } else {
+ Spline2Poly(aSpln,sal_False,aPoly);
+ if (aPoly.GetSize()>0) rOut.DrawPolyLine(aPoly);
+ }
+}
+
+/*************************************************************************
+|*
+|* CircType::Draw()
+|*
+*************************************************************************/
+void DrawSlideCirc(sal_Int16 cx, sal_Int16 cy, sal_Int16 rx, sal_Int16 ry, ObjAreaType& F, OutputDevice& rOut)
+{
+ sal_Int16 x1=cx-rx;
+ sal_Int16 y1=cy-ry;
+ sal_Int16 x2=cx+rx;
+ sal_Int16 y2=cy+ry;
+
+ sal_Int16 i,i0,b,b0;
+ sal_Int16 Int1,Int2;
+ sal_Int16 Col1,Col2;
+
+ rOut.SetLineColor();
+ Col1=F.FBFarbe & 0x87; Col2=F.FFarbe & 0x87;
+ Int1=100-F.FIntens; Int2=F.FIntens;
+ if (Int1==Int2) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.DrawEllipse(Rectangle(x1,y1,x2,y2));
+ } else {
+ b0=Int1;
+ switch (F.FBFarbe & 0x38) {
+ case 0x08: { // vertikal
+ Region ClipMerk=rOut.GetClipRegion();
+ i0=y1;
+ i=y1;
+ while (i<=y2) {
+ b=Int1+sal_Int16((sal_Int32)(Int2-Int1)*(sal_Int32)(i-y1) /(sal_Int32)(y2-y1+1));
+ if (b!=b0) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.SetClipRegion(Rectangle(x1,i0,x2,i-1));
+ rOut.DrawEllipse(Rectangle(x1,y1,x2,y2));
+ i0=i; b0=b;
+ }
+ i++;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.SetClipRegion(Rectangle(x1,i0,x2,y2));
+ rOut.DrawEllipse(Rectangle(x1,y1,x2,y2));
+ rOut.SetClipRegion(ClipMerk);
+ } break;
+ case 0x28: { // horizontal
+ Region ClipMerk=rOut.GetClipRegion();
+ i0=x1;
+ i=x1;
+ while (i<=x2) {
+ b=Int1+sal_Int16((sal_Int32)(Int2-Int1)*(sal_Int32)(i-x1) /(sal_Int32)(x2-x1+1));
+ if (b!=b0) {
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.SetClipRegion(Rectangle(i0,y1,i-1,y2));
+ rOut.DrawEllipse(Rectangle(x1,y1,x2,y2));
+ i0=i; b0=b;
+ }
+ i++;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int2,rOut);
+ rOut.SetClipRegion(Rectangle(i0,y1,x2,y2));
+ rOut.DrawEllipse(Rectangle(x1,y1,x2,y2));
+ rOut.SetClipRegion(ClipMerk);
+ } break;
+
+ case 0x18: case 0x38: { // Kreis
+ sal_Int16 MaxR;
+
+ if (rx<1) rx=1;
+ if (ry<1) ry=1;
+ MaxR=rx;
+ b0=Int2;
+ i0=MaxR; if (MaxR<1) MaxR=1;
+ i=MaxR;
+ while (i>=0) {
+ b=Int1+sal_Int16((sal_Int32(Int2-Int1)*sal_Int32(i)) /sal_Int32(MaxR));
+ if (b!=b0) {
+ sal_Int32 temp=sal_Int32(i0)*sal_Int32(ry)/sal_Int32(rx);
+ sal_Int16 j0=sal_Int16(temp);
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)b0,rOut);
+ rOut.DrawEllipse(Rectangle(cx-i0,cy-j0,cx+i0,cy+j0));
+ i0=i; b0=b;
+ }
+ i--;
+ }
+ SgfAreaColorIntens(F.FMuster,(sal_uInt8)Col1,(sal_uInt8)Col2,(sal_uInt8)Int1,rOut);
+ rOut.DrawEllipse(Rectangle(cx-i0,cy-i0,cx+i0,cy+i0));
+ } break; // Kreis
+ }
+ }
+}
+
+
+void CircType::Draw(OutputDevice& rOut)
+{
+ Rectangle aRect(Center.x-Radius.x,Center.y-Radius.y,Center.x+Radius.x,Center.y+Radius.y);
+
+ if (L.LMuster!=0) L.LMuster=1; // keine Linienmuster hier, nur an oder aus
+ SetArea(F,rOut);
+ if ((Flags & 0x03)==CircFull) {
+ if ((F.FBFarbe & 0x38)==0) {
+ SetLine(L,rOut);
+ rOut.DrawEllipse(aRect);
+ } else {
+ DrawSlideCirc(Center.x,Center.y,Radius.x,Radius.y,F,rOut);
+ if (L.LMuster!=0) {
+ SetLine(L,rOut);
+ rOut.SetFillColor();
+ rOut.DrawEllipse(aRect);
+ }
+ }
+ } else {
+ PointType a,b;
+ Point aStrt,aEnde;
+ double sn,cs;
+
+ a.x=Center.x+Radius.x; a.y=Center.y; b=a;
+ sn=sin(double(StartWink)*3.14159265359/18000);
+ cs=cos(double(StartWink)*3.14159265359/18000);
+ RotatePoint(a,Center.x,Center.y,sn,cs);
+ sn=sin(double(StartWink+RelWink)*3.14159265359/18000);
+ cs=cos(double(StartWink+RelWink)*3.14159265359/18000);
+ RotatePoint(b,Center.x,Center.y,sn,cs);
+ if (Radius.x!=Radius.y) {
+ if (Radius.x<1) Radius.x=1;
+ if (Radius.y<1) Radius.y=1;
+ a.y = a.y - Center.y;
+ b.y = b.y - Center.y;
+ a.y=iMulDiv(a.y,Radius.y,Radius.x);
+ b.y=iMulDiv(b.y,Radius.y,Radius.x);
+ a.y = a.y + Center.y;
+ b.y = b.y + Center.y;
+ }
+ aStrt=Point(a.x,a.y);
+ aEnde=Point(b.x,b.y);
+ SetLine(L,rOut);
+ switch (Flags & 0x03) {
+ case CircArc : rOut.DrawArc(aRect,aEnde,aStrt); break;
+ case CircSect:
+ case CircAbsn: rOut.DrawPie(aRect,aEnde,aStrt); break;
+ }
+ }
+}
+
+/*************************************************************************
+|*
+|* BmapType::Draw()
+|*
+*************************************************************************/
+
+void BmapType::Draw(OutputDevice& rOut)
+{
+ //ifstream aInp;
+ unsigned char nSgfTyp;
+ sal_uInt16 nVersion;
+ String aStr(
+ reinterpret_cast< char const * >(&Filename[ 1 ]),
+ (xub_StrLen)Filename[ 0 ], RTL_TEXTENCODING_UTF8 );
+ INetURLObject aFNam( aStr );
+
+ SvStream* pInp = ::utl::UcbStreamHelper::CreateStream( aFNam.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ );
+ if ( pInp )
+ {
+ nSgfTyp=CheckSgfTyp( *pInp,nVersion);
+ switch(nSgfTyp) {
+ case SGF_BITIMAGE: {
+ GraphicFilter aFlt;
+ Graphic aGrf;
+ aFlt.ImportGraphic(aGrf,aFNam);
+ aGrf.Draw(&rOut,Point(Pos1.x,Pos1.y),Size(Pos2.x-Pos1.x,Pos2.y-Pos1.y));
+ } break;
+ case SGF_SIMPVECT: {
+ GDIMetaFile aMtf;
+ SgfVectXofs=Pos1.x;
+ SgfVectYofs=Pos1.y;
+ SgfVectXmul=Pos2.x-Pos1.x;
+ SgfVectYmul=Pos2.y-Pos1.y;
+ SgfVectXdiv=0;
+ SgfVectYdiv=0;
+ SgfVectScal=sal_True;
+ SgfVectFilter(*pInp,aMtf);
+ SgfVectXofs=0;
+ SgfVectYofs=0;
+ SgfVectXmul=0;
+ SgfVectYmul=0;
+ SgfVectXdiv=0;
+ SgfVectYdiv=0;
+ SgfVectScal=sal_False;
+ aMtf.Play(&rOut);
+ } break;
+ }
+ delete pInp;
+ }
+}
+
+
+/*************************************************************************
+|*
+|* GrupType::...
+|*
+*************************************************************************/
+sal_uInt32 GrupType::GetSubPtr()
+{
+ return sal_uInt32(SbLo)+0x00010000*sal_uInt32(SbHi);
+}
+
+/*************************************************************************
+|*
+|* DrawObjkList()
+|*
+*************************************************************************/
+void DrawObjkList( SvStream& rInp, OutputDevice& rOut )
+{
+ ObjkType aObjk;
+ sal_uInt16 nGrpCnt=0;
+ sal_Bool bEnde=sal_False;
+ do {
+ rInp>>aObjk;
+ if (!rInp.GetError()) {
+ switch(aObjk.Art) {
+ case ObjStrk: { StrkType aStrk; rInp>>aStrk; if (!rInp.GetError()) aStrk.Draw(rOut); } break;
+ case ObjRect: { RectType aRect; rInp>>aRect; if (!rInp.GetError()) aRect.Draw(rOut); } break;
+ case ObjCirc: { CircType aCirc; rInp>>aCirc; if (!rInp.GetError()) aCirc.Draw(rOut); } break;
+ case ObjText: {
+ TextType aText;
+ rInp>>aText;
+ if (!rInp.GetError()) {
+ aText.Buffer=new UCHAR[aText.BufSize+1]; // Ein mehr fuer LookAhead bei CK-Trennung
+ rInp.Read((char* )aText.Buffer,aText.BufSize);
+ if (!rInp.GetError()) aText.Draw(rOut);
+ delete[] aText.Buffer;
+ }
+ } break;
+ case ObjBmap: {
+ BmapType aBmap;
+ rInp>>aBmap;
+ if (!rInp.GetError()) {
+ aBmap.Draw(rOut);
+ }
+ } break;
+ case ObjPoly: {
+ PolyType aPoly;
+ rInp>>aPoly;
+ if (!rInp.GetError()) {
+ aPoly.EckP=new PointType[aPoly.nPoints];
+ rInp.Read((char*)aPoly.EckP,4*aPoly.nPoints);
+#if defined OSL_BIGENDIAN
+ for(short i=0;i<aPoly.nPoints;i++) SWAPPOINT(aPoly.EckP[i]);
+#endif
+ if (!rInp.GetError()) aPoly.Draw(rOut);
+ delete[] aPoly.EckP;
+ }
+ } break;
+ case ObjSpln: {
+ SplnType aSpln;
+ rInp>>aSpln;
+ if (!rInp.GetError()) {
+ aSpln.EckP=new PointType[aSpln.nPoints];
+ rInp.Read((char*)aSpln.EckP,4*aSpln.nPoints);
+#if defined OSL_BIGENDIAN
+ for(short i=0;i<aSpln.nPoints;i++) SWAPPOINT(aSpln.EckP[i]);
+#endif
+ if (!rInp.GetError()) aSpln.Draw(rOut);
+ delete[] aSpln.EckP;
+ }
+ } break;
+ case ObjGrup: {
+ GrupType aGrup;
+ rInp>>aGrup;
+ if (!rInp.GetError()) {
+ rInp.Seek(rInp.Tell()+aGrup.Last); // Obj-Anhaengsel
+ if(aGrup.GetSubPtr()!=0L) nGrpCnt++;// DrawObjkList(rInp,rOut );
+ }
+ } break;
+ default: {
+ aObjk.Draw(rOut); // Objektbezeichnung auf 2. Screen
+ ObjkOverSeek(rInp,aObjk); // zum naechsten Objekt
+ }
+ }
+ } // if rInp
+ if (!rInp.GetError()) {
+ if (aObjk.Next==0L) {
+ if (nGrpCnt==0) bEnde=sal_True;
+ else nGrpCnt--;
+ }
+ } else {
+ bEnde=sal_True; // Lesefehler
+ }
+ } while (!bEnde);
+}
+
+/*************************************************************************
+|*
+|* SkipObjkList()
+|*
+*************************************************************************/
+void SkipObjkList(SvStream& rInp)
+{
+ ObjkType aObjk;
+ do
+ {
+ rInp>>aObjk;
+ if(aObjk.Art==ObjGrup) {
+ GrupType aGrup;
+ rInp>>aGrup;
+ rInp.Seek(rInp.Tell()+aGrup.Last); // Obj-Anhaengsel
+ if(aGrup.GetSubPtr()!=0L) SkipObjkList(rInp);
+ } else {
+ ObjkOverSeek(rInp,aObjk); // zum naechsten Objekt
+ }
+ } while (aObjk.Next!=0L && !rInp.GetError());
+}
+
+/*************************************************************************
+|*
+|* SgfFilterSDrw()
+|*
+*************************************************************************/
+sal_Bool SgfFilterSDrw( SvStream& rInp, SgfHeader&, SgfEntry&, GDIMetaFile& rMtf )
+{
+ sal_Bool bRet = sal_False;
+ PageType aPage;
+ VirtualDevice aOutDev;
+ OutputDevice* pOutDev;
+ sal_uLong nStdPos;
+ sal_uLong nZchPos;
+ sal_uInt16 Num;
+
+ pOutDev=&aOutDev;
+ DtHdOverSeek(rInp); // DataHeader weglesen
+
+ nStdPos=rInp.Tell();
+ do { // Standardseiten weglesen
+ rInp>>aPage;
+ if (aPage.nList!=0) SkipObjkList(rInp);
+ } while (aPage.Next!=0L && !rInp.GetError());
+
+// ShowMsg("Zeichnungseite(n)\n");
+ nZchPos=rInp.Tell();
+ rInp>>aPage;
+
+ rMtf.Record(pOutDev);
+ Num=aPage.StdPg;
+ if (Num!=0) {
+ rInp.Seek(nStdPos);
+ while(Num>1 && aPage.Next!=0L && !rInp.GetError()) { // Standardseite suchen
+ rInp>>aPage;
+ if (aPage.nList!=0) SkipObjkList(rInp);
+ Num--;
+ }
+ rInp>>aPage;
+ if(Num==1 && aPage.nList!=0L) DrawObjkList( rInp,*pOutDev );
+ rInp.Seek(nZchPos);
+ nZchPos=rInp.Tell();
+ rInp>>aPage;
+ }
+ if (aPage.nList!=0L) DrawObjkList(rInp,*pOutDev );
+
+ rMtf.Stop();
+ rMtf.WindStart();
+ MapMode aMap(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4));
+ rMtf.SetPrefMapMode(aMap);
+ rMtf.SetPrefSize(Size((sal_Int16)aPage.Paper.Size.x,(sal_Int16)aPage.Paper.Size.y));
+ bRet=sal_True;
+ return bRet;
+}
+
+
+
+/*************************************************************************
+|*
+|* SgfSDrwFilter()
+|*
+*************************************************************************/
+sal_Bool SgfSDrwFilter(SvStream& rInp, GDIMetaFile& rMtf, INetURLObject aIniPath )
+{
+#if OSL_DEBUG_LEVEL > 1 // Recordgroessen checken. Neuer Compiler hat vielleichte anderes Alignment!
+ if (sizeof(ObjTextType)!=ObjTextTypeSize) return sal_False;
+#endif
+
+ sal_uLong nFileStart; // Offset des SgfHeaders. Im allgemeinen 0.
+ SgfHeader aHead;
+ SgfEntry aEntr;
+ sal_uLong nNext;
+ sal_Bool bRdFlag=sal_False; // Grafikentry gelesen ?
+ sal_Bool bRet=sal_False; // Returncode
+
+ aIniPath.Append(rtl::OUString("sgf.ini"));
+
+ pSgfFonts = new SgfFontLst;
+
+ pSgfFonts->AssignFN( aIniPath.GetMainURL( INetURLObject::NO_DECODE ) );
+ nFileStart=rInp.Tell();
+ rInp>>aHead;
+ if (aHead.ChkMagic() && aHead.Typ==SgfStarDraw && aHead.Version==SGV_VERSION) {
+ nNext=aHead.GetOffset();
+ while (nNext && !bRdFlag && !rInp.GetError()) {
+ rInp.Seek(nFileStart+nNext);
+ rInp>>aEntr;
+ nNext=aEntr.GetOffset();
+ if (aEntr.Typ==aHead.Typ) {
+ bRet=SgfFilterSDrw( rInp,aHead,aEntr,rMtf );
+ }
+ } // while(nNext)
+ if (bRdFlag) {
+ if (!rInp.GetError()) bRet=sal_True; // Scheinbar Ok
+ }
+ }
+ delete pSgfFonts;
+ return(bRet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgvmain.hxx b/vcl/source/filter/sgvmain.hxx
new file mode 100644
index 000000000000..0d08ba310ef4
--- /dev/null
+++ b/vcl/source/filter/sgvmain.hxx
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _SGVMAIN_HXX
+#define _SGVMAIN_HXX
+
+#include <vcl/font.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+
+
+#define UCHAR unsigned char
+
+struct PointType {
+ sal_Int16 x;
+ sal_Int16 y;
+};
+
+#define SgfDpmm 40
+
+#define DtHdSize 256
+class DtHdType {
+public:
+ sal_uInt8 Reserved[256];
+ friend SvStream& operator>>(SvStream& rIStream, DtHdType& rDtHd);
+ friend void DtHdOverSeek(SvStream& rInp);
+};
+
+
+struct Seitenformat {
+ PointType Size; // 0.00mm...819.175mm (Papiergr��e)
+ sal_Int16 RandL; // links Rand auf
+ sal_Int16 RandR; // rechts dem Papier
+ sal_Int16 RandO; // oben Rand auf
+ sal_Int16 RandU; // unten dem Papier
+ sal_uInt8 PColor; // Future Use
+ sal_uInt8 PIntens; // erst recht Future use
+// sal_Bool BorderClip; // Objekte am Rand abschneiden (Schummel wg. Allignment unter NT)
+};
+
+
+#define PageSize 146
+class PageType {
+public:
+ sal_uInt32 Next; // N�chste Seite
+ sal_uInt32 nList; // Objektdaten, erster Record
+ sal_uInt32 ListEnd; // Objektdaten, letzter Record
+ Seitenformat Paper; // Papierdaten
+ sal_Bool BorderClip; // Objekte am Rand abschneiden (Schummel wg. Allignment unter NT)
+ sal_uInt8 StdPg; // welche Standardseite einblenden ?
+ PointType U; // Nullpunkt
+ sal_Int16 HlpLnH[20]; // Hilfslinien
+ sal_Int16 HlpLnV[20];
+ sal_uInt8 LnAnzH;
+ sal_uInt8 LnAnzV;
+ UCHAR PgName[32]; // Seitenname
+ friend SvStream& operator>>(SvStream& rIStream, PageType& rPage);
+};
+
+
+enum ObjArtType {ObjStrk,ObjRect,ObjPoly,ObjCirc,ObjSpln,
+ ObjText,ObjGrup,ObjBmap,ObjVirt,ObjTxtX,ObjMaxi};
+
+struct ObjLineType {
+ sal_uInt8 LFarbe; // [Index]
+ sal_uInt8 LBFarbe; // [Index]
+ sal_uInt8 LIntens; // [%]
+ sal_uInt8 LMuster; // [Index] inkl. Transparenz
+ sal_Int16 LMSize; // [Koeffizient/100]
+ sal_Int16 LDicke; // Strichst�rke
+};
+
+struct ObjAreaType {
+ sal_uInt8 FFarbe; // [Index]
+ sal_uInt8 FBFarbe; // [Index]
+ sal_uInt8 FIntens; // [%]
+ // Despite the "Dummy" in the name, and not being used anywhere in
+ // the code, these two fields are *essential*. These structs are
+ // 1:1 mappings of actual on-disk/wire file format structures...
+ // So don't clean the "unused dummy" fields away. (Actually it
+ // might well be that many other fields around here are never used
+ // in our code either.)
+ sal_uInt8 FDummy1; //
+ sal_Int16 FDummy2; //
+ sal_uInt16 FMuster; // [Index] inkl. Invers, Transparenz
+};
+
+#define ObjTextTypeSize 64
+class ObjTextType {
+public:
+ ObjLineType L; // Text-Outline (future)
+ ObjAreaType F; // Text innen
+ sal_uInt16 FontLo,FontHi;// z.B. 92500 (CG Times), zweigeteilt wegen DWordAllign in TextType.
+ sal_uInt16 Grad; // 0.5..32767.5 Pt - bei 1000 Pt sollte aber schlu� sein
+ sal_uInt16 Breite; // 1..65535% bitte nicht mehr als 500%
+ sal_uInt8 Justify; // 2 Bit Vert (Hi), 3 Bit Hor (Lo)
+ sal_uInt8 Kapit; // 1..255%
+ sal_uInt16 Schnitt; // 8 Flags
+ sal_uInt16 LnFeed; // 1..32767% vom max. Schriftgrad der Zeile
+ sal_uInt16 Slant; // Kursivwinkel 0.00..89.99� default 15.00� doppelt Breit angesehen)
+ sal_uInt8 ZAbst; // Zeichenabstand 0..255% (0=auf der Stelle; 100=normal; 200=Zeichen wird als
+ sal_sChar ChrVPos; // Zeichen V-Position default 0= on Baseline, 10= 5Pt drunter (-64..63�)
+ ObjLineType ShdL; // Schatten-Outline (neu 2.0)
+ ObjAreaType ShdF; // Schatten-innen (neu 2.0)
+ PointType ShdVers; // Schattenversatz Max.300.00%
+ sal_Bool ShdAbs; // True-> Schattenversatz ist absolut statt relativ zum Schriftgrad
+ sal_Bool NoSpc; // True-> kein Zwischenraum (f�r BackArea)
+ ObjAreaType BackF; // Hintergrundfl�che
+ sal_uInt32 GetFont();
+ void SetFont(sal_uInt32 FontID);
+};
+
+class Obj0Type { // SuperClass f�r Apple-VMT
+public:
+ virtual void Draw(OutputDevice& rOut);
+ virtual ~Obj0Type() {}
+};
+
+#define ObjkSize 20 /* eigentlich 21. Wg. Allignment ist Flags jedoch verschoben worden*/
+class ObjkType: public Obj0Type { // Grundkomponenten aller Stardraw-Objekte
+public:
+ sal_uInt32 Last;
+ sal_uInt32 Next;
+ sal_uInt16 MemSize; // in Bytes
+ PointType ObjMin; // XY-Minimum des Objekts
+ PointType ObjMax; // XY-Maximum des Objekts
+ sal_uInt8 Art;
+ sal_uInt8 Layer;
+// sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ friend SvStream& operator>>(SvStream& rIStream, ObjkType& rObjk);
+ friend sal_Bool ObjOverSeek(SvStream& rInp, ObjkType& rObjk);
+ virtual void Draw(OutputDevice& rOut);
+};
+
+
+#define StrkSize 38
+class StrkType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 LEnden; // Linienenden
+ ObjLineType L;
+ PointType Pos1; // Anfangspunkt
+ PointType Pos2; // Endpunkt
+ friend SvStream& operator>>(SvStream& rIStream, StrkType& rStrk);
+ virtual void Draw(OutputDevice& rOut);
+};
+
+
+#define RectSize 52
+class RectType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 Reserve;
+ ObjLineType L;
+ ObjAreaType F;
+ PointType Pos1; // LO-Ecke = Bezugspunkt
+ PointType Pos2; // R-Ecke
+ sal_Int16 Radius; // Eckenradius
+ sal_uInt16 DrehWink; // 315...<45
+ sal_uInt16 Slant; // >270...<90
+ friend SvStream& operator>>(SvStream& rIStream, RectType& rRect);
+ virtual void Draw(OutputDevice& rOut);
+};
+
+
+#define PolySize 44
+class PolyType: public ObjkType { // identisch mit Spline !
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 LEnden; // nur f�r Polyline
+ ObjLineType L;
+ ObjAreaType F; // nicht f�r Polyline
+ sal_uInt8 nPoints;
+ sal_uInt8 Reserve;
+ sal_uInt32 SD_EckP; // Zeiger auf die Eckpunkte (StarDraw)
+ PointType* EckP; // Zeiger auf die Eckpunkte (StarView (wird nicht von Disk gelesen!))
+ friend SvStream& operator>>(SvStream& rIStream, PolyType& rPoly);
+ virtual void Draw(OutputDevice& rOut);
+};
+#define PolyClosBit 0x01 // Unterarten von Poly: 0: PolyLine 1: Polygon
+
+
+#define SplnSize 44
+class SplnType: public ObjkType { // identisch mit Poly !
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 LEnden; // nur f�r nSpline
+ ObjLineType L;
+ ObjAreaType F; // nicht f�r nSpline
+ sal_uInt8 nPoints;
+ sal_uInt8 Reserve;
+ sal_uInt32 SD_EckP; // Zeiger auf die Eckpunkte (StarDraw)
+ PointType* EckP; // Zeiger auf die Eckpunkte (StarView (wird nicht von Disk gelesen!))
+ friend SvStream& operator>>(SvStream& rIStream, SplnType& rSpln);
+ virtual void Draw(OutputDevice& rOut);
+};
+// Unterarten von Spline: siehe Poly
+
+
+#define CircSize 52
+class CircType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 LEnden; // nur Bogen (Kr & El)
+ ObjLineType L;
+ ObjAreaType F; // nicht f�r Bogen (Kr & El)
+ PointType Center; // Mittelpunkt
+ PointType Radius; // Radius
+ sal_uInt16 DrehWink; // nur Ellipse
+ sal_uInt16 StartWink; // � nicht f�r Vollkreis
+ sal_uInt16 RelWink; // � und Vollellipse
+ friend SvStream& operator>>(SvStream& rIStream, CircType& rCirc);
+ virtual void Draw(OutputDevice& rOut);
+};
+#define CircFull 0x00 /* Unterarten von Kreis: 0: Kreis */
+#define CircSect 0x01 /* 1: Kreissektor */
+#define CircAbsn 0x02 /* 2: Kreisabschnitt */
+#define CircArc 0x03 /* 3: Kreisbogen */
+
+
+#define TextSize 116
+class TextType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 Reserve; // f�r Word Allign
+ ObjTextType T; // 64 Bytes << DWord-Allign bei FontID erforderlich
+ PointType Pos1; // Bezugspunkt (ObenLinks)
+ PointType Pos2; // (untenRechts)
+ sal_Int16 TopOfs; // Von Oberkante bis Textbegin (future f�r vJustify)
+ sal_uInt16 DrehWink; // 0...<360
+ sal_uInt16 BoxSlant; // >270...<90 (nur Box)
+ sal_uInt16 BufSize; // Gr��e von Buf f�r Load, Save, Copy und so
+ sal_uInt16 BufLo,BufHi;// (UCHAR*) Zeiger auf den Textbuffer << ShortArr, weil sonst DWord-Allign erforderlich
+ sal_uInt16 ExtLo,ExtHi;// (Ptr) Text �ber mehrere Rahmen << ShortArr, weil sonst DWord-Allign erforderlich
+ PointType FitSize; // Ursprungsgr��e f�r Fit2Size
+ sal_Int16 FitBreit; // Breite zum formatieren bei Fit2Size
+ UCHAR* Buffer; // Diese Variable wird nicht durch Lesen von Disk gef�llt, sondern explizit!
+ friend SvStream& operator>>(SvStream& rIStream, TextType& rText);
+ virtual void Draw(OutputDevice& rOut);
+};
+#define TextOutlBit 0x01 /* 1=Sourcecode f�r Outliner (wird von DrawObjekt() ignoriert) */
+#define TextFitSBit 0x02 /* Bit1: 1=Text-FitToSize, auch Outliner (2.0) */
+#define TextFitZBit 0x08 /* Bit3: 1=Fit2Size Zeilenweise (2.0) */
+#define TextDrftBit 0x04 /* Bit2: 1=DraftDraw (2.0) */
+#define TextFitBits (TextFitSBit | TextFitZBit)
+
+
+enum GrafStat {NoGraf,Pic,Pcx,Hpgl,Img,Msp,Tiff,Dxf,Lot,Usr,Sgf};
+
+#define BmapSize 132
+class BmapType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ sal_uInt8 Reserve;
+ ObjAreaType F; // Farbe und Muster der 1-Plane Bitmap
+ PointType Pos1;
+ PointType Pos2;
+ sal_uInt16 DrehWink; // 315...<45 (Future)
+ sal_uInt16 Slant; // >270...<90 (Future)
+ UCHAR Filename[80]; // Pfad
+ PointType PixSize; // Gr��e in Pixel (0 bei Vektor)
+ GrafStat Format; // siehe GpmDef.Pas
+ sal_uInt8 nPlanes; // Anzahl der Bitplanes (0 bei Vektor)
+ sal_Bool RawOut; // als Raw ausgeben ?
+ sal_Bool InvOut; // invertiert ausgeben ?
+ sal_Bool LightOut; // aufhellen? (SD20)
+ sal_uInt8 GrfFlg; // (SD20) 0=nSGF 1=Pcx 2=Hpgl 4=Raw $FF=Undef(f�r Fix in DrawBmp)
+
+ INetURLObject aFltPath; // F�r GraphicFilter
+ friend SvStream& operator>>(SvStream& rIStream, BmapType& rBmap);
+ virtual void Draw(OutputDevice& rOut);
+ void SetPaths( const INetURLObject rFltPath );
+};
+
+
+#define GrupSize 48
+class GrupType: public ObjkType {
+public:
+ sal_uInt8 Flags; // (Schummel f�r Allignment unter NT)
+ UCHAR Name[13]; // Name der Gruppe
+ sal_uInt16 SbLo,SbHi; // (Ptr) Gruppenliste << ShortArr, weil sonst DWord Allign erforderlich
+ sal_uInt16 UpLo,UpHi; // (Ptr) Vaterliste << ShortArr, weil sonst DWord Allign erforderlich
+ sal_uInt16 ChartSize; // Speicherbedarf der Diagrammstruktur Struktur
+ sal_uInt32 ChartPtr; // Diagrammstruktur
+ sal_uInt32 GetSubPtr(); // hier nur zum Checken, ob Sublist evtl. leer ist.
+ friend SvStream& operator>>(SvStream& rIStream, GrupType& rGrup);
+// virtual void Draw(OutputDevice& rOut);
+};
+
+
+void SetLine(ObjLineType& rLine, OutputDevice& rOut);
+void SetArea(ObjAreaType& rArea, OutputDevice& rOut);
+Color Sgv2SvFarbe(sal_uInt8 nFrb1, sal_uInt8 nFrb2, sal_uInt8 nInts);
+void RotatePoint(PointType& P, sal_Int16 cx, sal_Int16 cy, double sn, double cs);
+void RotatePoint(Point& P, sal_Int16 cx, sal_Int16 cy, double sn, double cs);
+sal_Int16 iMulDiv(sal_Int16 a, sal_Int16 Mul, sal_Int16 Div);
+sal_uInt16 MulDiv(sal_uInt16 a, sal_uInt16 Mul, sal_uInt16 Div);
+
+
+class SgfFontOne {
+public:
+ SgfFontOne* Next; // Zeiger f�r Listenverkettung
+ sal_uInt32 IFID;
+ sal_Bool Bold;
+ sal_Bool Ital;
+ sal_Bool Sans;
+ sal_Bool Serf;
+ sal_Bool Fixd;
+ FontFamily SVFamil;
+ CharSet SVChSet;
+ String SVFName; // z.B. "Times New Roman" = 15 Chars
+ sal_uInt16 SVWidth; // Durchschnittliche Zeichenbreite in %
+ SgfFontOne();
+ void ReadOne(const rtl::OString& rID, rtl::OString& rDsc);
+};
+
+class SgfFontLst {
+public:
+ String FNam; // vollst�ndiger Filename des Inifiles
+ SgfFontOne* pList; // Listenanfang
+ SgfFontOne* Last; // Listenende
+ sal_uInt32 LastID; // f�r schnelleren Zugriff bei Wiederholungen
+ SgfFontOne* LastLn; // f�r schnelleren Zugriff bei Wiederholungen
+ sal_Bool Tried;
+ SgfFontLst();
+ ~SgfFontLst();
+ void AssignFN(const String& rFName);
+ void ReadList();
+ void RausList();
+ SgfFontOne* GetFontDesc(sal_uInt32 ID);
+};
+
+#endif //_SGVMAIN_HXX
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgvspln.cxx b/vcl/source/filter/sgvspln.cxx
new file mode 100644
index 000000000000..2449b743ce11
--- /dev/null
+++ b/vcl/source/filter/sgvspln.cxx
@@ -0,0 +1,861 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <math.h>
+
+
+#include <tools/poly.hxx>
+
+extern "C" {
+
+/*.pn 277 */
+/*.hlAnhang: C - Programme*/
+/*.hrKonstanten- und Macro-Definitionen*/
+/*.fe Die Include-Datei u_const.h ist in das Verzeichnis zu stellen, */
+/*.fe wo der Compiler nach Include-Dateien sucht. */
+
+
+/*----------------------- FILE u_const.h ---------------------------*/
+
+#define IEEE
+
+/* IEEE - Norm fuer die Darstellung von Gleitkommazahlen:
+
+ 8 Byte lange Gleitkommazahlen, mit
+
+ 53 Bit Mantisse ==> Mantissenbereich: 2 hoch 52 versch. Zahlen
+ mit 0.1 <= Zahl < 1.0,
+ 1 Vorzeichen-Bit
+ 11 Bit Exponent ==> Exponentenbereich: -1024...+1023
+
+ Die 1. Zeile ( #define IEEE ) ist zu loeschen, falls die Maschine
+ bzw. der Compiler keine Gleitpunktzahlen gemaess der IEEE-Norm
+ benutzt. Zusaetzlich muessen die Zahlen MAXEXPON, MINEXPON
+ (s.u.) angepasst werden.
+ */
+
+#ifdef IEEE /*----------- Falls IEEE Norm --------------------*/
+
+#define MACH_EPS 2.220446049250313e-016 /* Maschinengenauigkeit */
+ /* IBM-AT: = 2 hoch -52 */
+/* MACH_EPS ist die kleinste positive, auf der Maschine darstellbare
+ Zahl x, die der Bedingung genuegt: 1.0 + x > 1.0 */
+
+#define EPSQUAD 4.930380657631324e-032
+#define EPSROOT 1.490116119384766e-008
+
+#define POSMAX 8.98846567431158e+307 /* groesste positive Zahl */
+#define POSMIN 5.56268464626800e-309 /* kleinste positive Zahl */
+#define MAXROOT 9.48075190810918e+153
+
+#define BASIS 2 /* Basis der Zahlendarst. */
+#ifndef PI
+#define PI 3.141592653589793e+000
+#endif
+#define EXP_1 2.718281828459045e+000
+
+#else /*------------------ sonst -----------------------*/
+
+double exp (double);
+double atan (double);
+double pow (double,double);
+double sqrt (double);
+
+double masch() /* MACH_EPS maschinenunabhaengig bestimmen */
+{
+ double eps = 1.0, x = 2.0, y = 1.0;
+ while ( y < x )
+ { eps *= 0.5;
+ x = 1.0 + eps;
+ }
+ eps *= 2.0; return (eps);
+}
+
+short basis() /* BASIS maschinenunabhaengig bestimmen */
+{
+ double x = 1.0, one = 1.0, b = 1.0;
+
+ while ( (x + one) - x == one ) x *= 2.0;
+ while ( (x + b) == x ) b *= 2.0;
+
+ return ( (short) ((x + b) - x) );
+}
+
+#define BASIS basis() /* Basis der Zahlendarst. */
+
+/* Falls die Maschine (der Compiler) keine IEEE-Darstellung fuer
+ Gleitkommazahlen nutzt, muessen die folgenden 2 Konstanten an-
+ gepasst werden.
+ */
+
+#define MAXEXPON 1023.0 /* groesster Exponent */
+#define MINEXPON -1024.0 /* kleinster Exponent */
+
+
+#define MACH_EPS masch()
+#define EPSQUAD MACH_EPS * MACH_EPS
+#define EPSROOT sqrt(MACH_EPS)
+
+#define POSMAX pow ((double) BASIS, MAXEXPON)
+#define POSMIN pow ((double) BASIS, MINEXPON)
+#define MAXROOT sqrt(POSMAX)
+
+#define PI 4.0 * atan (1.0)
+#define EXP_1 exp(1.0)
+
+#endif /*-------------- ENDE ifdef ----------------------*/
+
+
+#define NEGMAX -POSMIN /* groesste negative Zahl */
+#define NEGMIN -POSMAX /* kleinste negative Zahl */
+
+/* Definition von Funktionsmakros:
+ */
+
+#define abs(X) ((X) >= 0 ? (X) : -(X)) /* Absolutbetrag von X */
+#define sign(X, Y) (Y < 0 ? -abs(X) : abs(X)) /* Vorzeichen von */
+ /* Y mal abs(X) */
+#define sqr(X) ((X) * (X)) /* Quadrat von X */
+
+/*------------------- ENDE FILE u_const.h --------------------------*/
+
+
+
+
+
+
+
+
+
+/*.HL Anhang: C - Programme*/
+/*.HRGleichungssysteme fuer Tridiagonalmatrizen*/
+
+/*.FE P 3.7 TRIDIAGONALE GLEICHUNGSSYSTEME*/
+
+
+/*---------------------- MODUL TRIDIAGONAL ------------------------*/
+
+sal_uInt16 TriDiagGS(sal_Bool rep, sal_uInt16 n, double* lower,
+ double* diag, double* upper, double* b)
+ /************************/
+ /* GAUSS-Verfahren fuer */
+ /* Tridiagonalmatrizen */
+ /************************/
+
+/*====================================================================*/
+/* */
+/* trdiag bestimmt die Loesung x des linearen Gleichungssystems */
+/* A * x = b mit tridiagonaler n x n Koeffizientenmatrix A, die in */
+/* den 3 Vektoren lower, upper und diag wie folgt abgespeichert ist: */
+/* */
+/* ( diag[0] upper[0] 0 0 . . . 0 ) */
+/* ( lower[1] diag[1] upper[1] 0 . . . ) */
+/* ( 0 lower[2] diag[2] upper[2] 0 . ) */
+/* A = ( . 0 lower[3] . . . ) */
+/* ( . . . . . 0 ) */
+/* ( . . . . . ) */
+/* ( . . . upper[n-2] ) */
+/* ( 0 . . . 0 lower[n-1] diag[n-1] ) */
+/* */
+/*====================================================================*/
+/* */
+/* Anwendung: */
+/* ========= */
+/* Vorwiegend fuer diagonaldominante Tridiagonalmatrizen, wie */
+/* sie bei der Spline-Interpolation auftreten. */
+/* Fuer diagonaldominante Matrizen existiert immer eine LU- */
+/* Zerlegung; fuer nicht diagonaldominante Tridiagonalmatrizen */
+/* sollte die Funktion band vorgezogen werden, da diese mit */
+/* Spaltenpivotsuche arbeitet und daher numerisch stabiler ist. */
+/* */
+/*====================================================================*/
+/* */
+/* Eingabeparameter: */
+/* ================ */
+/* n Dimension der Matrix ( > 1 ) sal_uInt16 n */
+/* */
+/* lower untere Nebendiagonale double lower[n] */
+/* diag Hauptdiagonale double diag[n] */
+/* upper obere Nebendiagonale double upper[n] */
+/* */
+/* bei rep != 0 enthalten lower, diag und upper die */
+/* Dreieckzerlegung der Ausgangsmatrix. */
+/* */
+/* b rechte Seite des Systems double b[n] */
+/* rep = 0 erstmaliger Aufruf sal_Bool rep */
+/* !=0 wiederholter Aufruf */
+/* fuer gleiche Matrix, */
+/* aber verschiedenes b. */
+/* */
+/* Ausgabeparameter: */
+/* ================ */
+/* b Loesungsvektor des Systems; double b[n] */
+/* die urspruengliche rechte Seite wird ueberspeichert */
+/* */
+/* lower ) enthalten bei rep = 0 die Zerlegung der Matrix; */
+/* diag ) die urspruenglichen Werte von lower u. diag werden */
+/* upper ) ueberschrieben */
+/* */
+/* Die Determinante der Matrix ist bei rep = 0 durch */
+/* det A = diag[0] * ... * diag[n-1] bestimmt. */
+/* */
+/* Rueckgabewert: */
+/* ============= */
+/* = 0 alles ok */
+/* = 1 n < 2 gewaehlt */
+/* = 2 Die Dreieckzerlegung der Matrix existiert nicht */
+/* */
+/*====================================================================*/
+/* */
+/* Benutzte Funktionen: */
+/* =================== */
+/* */
+/* Aus der C Bibliothek: fabs() */
+/* */
+/*====================================================================*/
+
+/*.cp 5 */
+{
+ sal_uInt16 i;
+ short j;
+
+// double fabs(double);
+
+ if ( n < 2 ) return(1); /* n mindestens 2 */
+
+ /* Wenn rep = 0 ist, */
+ /* Dreieckzerlegung der */
+ if (rep == 0) /* Matrix u. det be- */
+ { /* stimmen */
+ for (i = 1; i < n; i++)
+ { if ( fabs(diag[i-1]) < MACH_EPS ) /* Wenn ein diag[i] = 0 */
+ return(2); /* ist, ex. keine Zerle- */
+ lower[i] /= diag[i-1]; /* gung. */
+ diag[i] -= lower[i] * upper[i-1];
+ }
+ }
+
+ if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
+
+ for (i = 1; i < n; i++) /* Vorwaertselimination */
+ b[i] -= lower[i] * b[i-1];
+
+ b[n-1] /= diag[n-1]; /* Rueckwaertselimination */
+ for (j = n-2; j >= 0; j--) {
+ i=j;
+ b[i] = ( b[i] - upper[i] * b[i+1] ) / diag[i];
+ }
+ return(0);
+}
+
+/*----------------------- ENDE TRIDIAGONAL -------------------------*/
+
+
+
+
+
+
+
+
+
+/*.HL Anhang: C - Programme*/
+/*.HRGleichungssysteme mit zyklisch tridiagonalen Matrizen*/
+
+/*.FE P 3.8 SYSTEME MIT ZYKLISCHEN TRIDIAGONALMATRIZEN */
+
+
+/*---------------- MODUL ZYKLISCH TRIDIAGONAL ----------------------*/
+
+
+sal_uInt16 ZyklTriDiagGS(sal_Bool rep, sal_uInt16 n, double* lower, double* diag,
+ double* upper, double* lowrow, double* ricol, double* b)
+ /******************************/
+ /* Systeme mit zyklisch tri- */
+ /* diagonalen Matrizen */
+ /******************************/
+
+/*====================================================================*/
+/* */
+/* tzdiag bestimmt die Loesung x des linearen Gleichungssystems */
+/* A * x = b mit zyklisch tridiagonaler n x n Koeffizienten- */
+/* matrix A, die in den 5 Vektoren lower, upper, diag, lowrow und */
+/* ricol wie folgt abgespeichert ist: */
+/* */
+/* ( diag[0] upper[0] 0 0 . . 0 ricol[0] ) */
+/* ( lower[1] diag[1] upper[1] 0 . . 0 ) */
+/* ( 0 lower[2] diag[2] upper[2] 0 . ) */
+/* A = ( . 0 lower[3] . . . . ) */
+/* ( . . . . . 0 ) */
+/* ( . . . . . ) */
+/* ( 0 . . . upper[n-2] ) */
+/* ( lowrow[0] 0 . . 0 lower[n-1] diag[n-1] ) */
+/* */
+/* Speicherplatz fuer lowrow[1],..,lowrow[n-3] und ricol[1],..., */
+/* ricol[n-3] muss zusaetzlich bereitgestellt werden, da dieser */
+/* fuer die Aufnahme der Zerlegungsmatrix verfuegbar sein muss, die */
+/* auf die 5 genannten Vektoren ueberspeichert wird. */
+/* */
+/*====================================================================*/
+/* */
+/* Anwendung: */
+/* ========= */
+/* Vorwiegend fuer diagonaldominante zyklische Tridiagonalmatri- */
+/* zen wie sie bei der Spline-Interpolation auftreten. */
+/* Fuer diagonaldominante Matrizen existiert immer eine LU- */
+/* Zerlegung. */
+/* */
+/*====================================================================*/
+/* */
+/* Eingabeparameter: */
+/* ================ */
+/* n Dimension der Matrix ( > 2 ) sal_uInt16 n */
+/* lower untere Nebendiagonale double lower[n] */
+/* diag Hauptdiagonale double diag[n] */
+/* upper obere Nebendiagonale double upper[n] */
+/* b rechte Seite des Systems double b[n] */
+/* rep = 0 erstmaliger Aufruf sal_Bool rep */
+/* !=0 wiederholter Aufruf */
+/* fuer gleiche Matrix, */
+/* aber verschiedenes b. */
+/* */
+/* Ausgabeparameter: */
+/* ================ */
+/* b Loesungsvektor des Systems, double b[n] */
+/* die urspruengliche rechte Seite wird ueberspeichert */
+/* */
+/* lower ) enthalten bei rep = 0 die Zerlegung der Matrix; */
+/* diag ) die urspruenglichen Werte von lower u. diag werden */
+/* upper ) ueberschrieben */
+/* lowrow ) double lowrow[n-2] */
+/* ricol ) double ricol[n-2] */
+/* */
+/* Die Determinante der Matrix ist bei rep = 0 durch */
+/* det A = diag[0] * ... * diag[n-1] bestimmt. */
+/* */
+/* Rueckgabewert: */
+/* ============= */
+/* = 0 alles ok */
+/* = 1 n < 3 gewaehlt */
+/* = 2 Die Zerlegungsmatrix existiert nicht */
+/* */
+/*====================================================================*/
+/* */
+/* Benutzte Funktionen: */
+/* =================== */
+/* */
+/* Aus der C Bibliothek: fabs() */
+/* */
+/*====================================================================*/
+
+/*.cp 5 */
+{
+ double temp; // fabs(double);
+ sal_uInt16 i;
+ short j;
+
+ if ( n < 3 ) return(1);
+
+ if (rep == 0) /* Wenn rep = 0 ist, */
+ { /* Zerlegung der */
+ lower[0] = upper[n-1] = 0.0; /* Matrix berechnen. */
+
+ if ( fabs (diag[0]) < MACH_EPS ) return(2);
+ /* Ist ein Diagonalelement */
+ temp = 1.0 / diag[0]; /* betragsmaessig kleiner */
+ upper[0] *= temp; /* MACH_EPS, so ex. keine */
+ ricol[0] *= temp; /* Zerlegung. */
+
+ for (i = 1; i < n-2; i++)
+ { diag[i] -= lower[i] * upper[i-1];
+ if ( fabs(diag[i]) < MACH_EPS ) return(2);
+ temp = 1.0 / diag[i];
+ upper[i] *= temp;
+ ricol[i] = -lower[i] * ricol[i-1] * temp;
+ }
+
+ diag[n-2] -= lower[n-2] * upper[n-3];
+ if ( fabs(diag[n-2]) < MACH_EPS ) return(2);
+
+ for (i = 1; i < n-2; i++)
+ lowrow[i] = -lowrow[i-1] * upper[i-1];
+
+ lower[n-1] -= lowrow[n-3] * upper[n-3];
+ upper[n-2] = ( upper[n-2] - lower[n-2] * ricol[n-3] ) / diag[n-2];
+
+ for (temp = 0.0, i = 0; i < n-2; i++)
+ temp -= lowrow[i] * ricol[i];
+ diag[n-1] += temp - lower[n-1] * upper[n-2];
+
+ if ( fabs(diag[n-1]) < MACH_EPS ) return(2);
+ } /* end if ( rep == 0 ) */
+
+ b[0] /= diag[0]; /* Vorwaertselemination */
+ for (i = 1; i < n-1; i++)
+ b[i] = ( b[i] - b[i-1] * lower[i] ) / diag[i];
+
+ for (temp = 0.0, i = 0; i < n-2; i++)
+ temp -= lowrow[i] * b[i];
+
+ b[n-1] = ( b[n-1] + temp - lower[n-1] * b[n-2] ) / diag[n-1];
+
+ b[n-2] -= b[n-1] * upper[n-2]; /* Rueckwaertselimination */
+ for (j = n-3; j >= 0; j--) {
+ i=j;
+ b[i] -= upper[i] * b[i+1] + ricol[i] * b[n-1];
+ }
+ return(0);
+}
+
+/*------------------ ENDE ZYKLISCH TRIDIAGONAL ---------------------*/
+
+
+} // extern "C"
+
+
+/*************************************************************************
+|*
+|* NaturalSpline()
+|*
+|* Beschreibung Berechnet die Koeffizienten eines natuerlichen
+|* kubischen Polynomsplines mit n Stuetzstellen.
+|*
+*************************************************************************/
+
+sal_uInt16 NaturalSpline(sal_uInt16 n, double* x, double* y,
+ double Marg0, double MargN,
+ sal_uInt8 MargCond,
+ double* b, double* c, double* d)
+{
+ sal_uInt16 i;
+ double* a;
+ double* h;
+ sal_uInt16 error;
+
+ if (n<2) return 1;
+ if ( (MargCond & ~3) ) return 2;
+ a=new double[n+1];
+ h=new double[n+1];
+ for (i=0;i<n;i++) {
+ h[i]=x[i+1]-x[i];
+ if (h[i]<=0.0) { delete[] a; delete[] h; return 1; }
+ }
+ for (i=0;i<n-1;i++) {
+ a[i]=3.0*((y[i+2]-y[i+1])/h[i+1]-(y[i+1]-y[i])/h[i]);
+ b[i]=h[i];
+ c[i]=h[i+1];
+ d[i]=2.0*(h[i]+h[i+1]);
+ }
+ switch (MargCond) {
+ case 0: {
+ if (n==2) {
+ a[0]=a[0]/3.0;
+ d[0]=d[0]*0.5;
+ } else {
+ a[0] =a[0]*h[1]/(h[0]+h[1]);
+ a[n-2]=a[n-2]*h[n-2]/(h[n-1]+h[n-2]);
+ d[0] =d[0]-h[0];
+ d[n-2]=d[n-2]-h[n-1];
+ c[0] =c[0]-h[0];
+ b[n-2]=b[n-2]-h[n-1];
+ }
+ }
+ case 1: {
+ a[0] =a[0]-1.5*((y[1]-y[0])/h[0]-Marg0);
+ a[n-2]=a[n-2]-1.5*(MargN-(y[n]-y[n-1])/h[n-1]);
+ d[0] =d[0]-h[0]*0.5;
+ d[n-2]=d[n-2]-h[n-1]*0.5;
+ }
+ case 2: {
+ a[0] =a[0]-h[0]*Marg0*0.5;
+ a[n-2]=a[n-2]-h[n-1]*MargN*0.5;
+ }
+ case 3: {
+ a[0] =a[0]+Marg0*h[0]*h[0]*0.5;
+ a[n-2]=a[n-2]-MargN*h[n-1]*h[n-1]*0.5;
+ d[0] =d[0]+h[0];
+ d[n-2]=d[n-2]+h[n-1];
+ }
+ } // switch MargCond
+ if (n==2) {
+ c[1]=a[0]/d[0];
+ } else {
+ error=TriDiagGS(sal_False,n-1,b,d,c,a);
+ if (error!=0) { delete[] a; delete[] h; return error+2; }
+ for (i=0;i<n-1;i++) c[i+1]=a[i];
+ }
+ switch (MargCond) {
+ case 0: {
+ if (n==2) {
+ c[2]=c[1];
+ c[0]=c[1];
+ } else {
+ c[0]=c[1]+h[0]*(c[1]-c[2])/h[1];
+ c[n]=c[n-1]+h[n-1]*(c[n-1]-c[n-2])/h[n-2];
+ }
+ }
+ case 1: {
+ c[0]=1.5*((y[1]-y[0])/h[0]-Marg0);
+ c[0]=(c[0]-c[1]*h[0]*0.5)/h[0];
+ c[n]=1.5*((y[n]-y[n-1])/h[n-1]-MargN);
+ c[n]=(c[n]-c[n-1]*h[n-1]*0.5)/h[n-1];
+ }
+ case 2: {
+ c[0]=Marg0*0.5;
+ c[n]=MargN*0.5;
+ }
+ case 3: {
+ c[0]=c[1]-Marg0*h[0]*0.5;
+ c[n]=c[n-1]+MargN*h[n-1]*0.5;
+ }
+ } // switch MargCond
+ for (i=0;i<n;i++) {
+ b[i]=(y[i+1]-y[i])/h[i]-h[i]*(c[i+1]+2.0*c[i])/3.0;
+ d[i]=(c[i+1]-c[i])/(3.0*h[i]);
+ }
+ delete[] a;
+ delete[] h;
+ return 0;
+}
+
+
+/*************************************************************************
+|*
+|* PeriodicSpline()
+|*
+|* Beschreibung Berechnet die Koeffizienten eines periodischen
+|* kubischen Polynomsplines mit n Stuetzstellen.
+|*
+*************************************************************************/
+
+
+sal_uInt16 PeriodicSpline(sal_uInt16 n, double* x, double* y,
+ double* b, double* c, double* d)
+{ // Arrays muessen von [0..n] dimensioniert sein!
+ sal_uInt16 Error;
+ sal_uInt16 i,im1,nm1; //integer
+ double hr,hl;
+ double* a;
+ double* lowrow;
+ double* ricol;
+
+ if (n<2) return 4;
+ nm1=n-1;
+ for (i=0;i<=nm1;i++) if (x[i+1]<=x[i]) return 2; // muss streng nonoton fallend sein!
+ if (y[n]!=y[0]) return 3; // Anfang muss gleich Ende sein!
+
+ a =new double[n+1];
+ lowrow=new double[n+1];
+ ricol =new double[n+1];
+
+ if (n==2) {
+ c[1]=3.0*((y[2]-y[1])/(x[2]-x[1]));
+ c[1]=c[1]-3.0*((y[i]-y[0])/(x[1]-x[0]));
+ c[1]=c[1]/(x[2]-x[0]);
+ c[2]=-c[1];
+ } else {
+ for (i=1;i<=nm1;i++) {
+ im1=i-1;
+ hl=x[i]-x[im1];
+ hr=x[i+1]-x[i];
+ b[im1]=hl;
+ d[im1]=2.0*(hl+hr);
+ c[im1]=hr;
+ a[im1]=3.0*((y[i+1]-y[i])/hr-(y[i]-y[im1])/hl);
+ }
+ hl=x[n]-x[nm1];
+ hr=x[1]-x[0];
+ b[nm1]=hl;
+ d[nm1]=2.0*(hl+hr);
+ lowrow[0]=hr;
+ ricol[0]=hr;
+ a[nm1]=3.0*((y[1]-y[0])/hr-(y[n]-y[nm1])/hl);
+ Error=ZyklTriDiagGS(sal_False,n,b,d,c,lowrow,ricol,a);
+ if ( Error != 0 )
+ {
+ delete[] a;
+ delete[] lowrow;
+ delete[] ricol;
+ return(Error+4);
+ }
+ for (i=0;i<=nm1;i++) c[i+1]=a[i];
+ }
+ c[0]=c[n];
+ for (i=0;i<=nm1;i++) {
+ hl=x[i+1]-x[i];
+ b[i]=(y[i+1]-y[i])/hl;
+ b[i]=b[i]-hl*(c[i+1]+2.0*c[i])/3.0;
+ d[i]=(c[i+1]-c[i])/hl/3.0;
+ }
+ delete[] a;
+ delete[] lowrow;
+ delete[] ricol;
+ return 0;
+}
+
+
+
+/*************************************************************************
+|*
+|* ParaSpline()
+|*
+|* Beschreibung Berechnet die Koeffizienten eines parametrischen
+|* natuerlichen oder periodischen kubischen
+|* Polynomsplines mit n Stuetzstellen.
+|*
+*************************************************************************/
+
+sal_uInt16 ParaSpline(sal_uInt16 n, double* x, double* y, sal_uInt8 MargCond,
+ double Marg01, double Marg02,
+ double MargN1, double MargN2,
+ sal_Bool CondT, double* T,
+ double* bx, double* cx, double* dx,
+ double* by, double* cy, double* dy)
+{
+ sal_uInt16 Error;
+ sal_uInt16 i;
+ double deltX,deltY,delt,
+ alphX = 0,alphY = 0,
+ betX = 0,betY = 0;
+
+ if (n<2) return 1;
+ if ((MargCond & ~3) && (MargCond != 4)) return 2; // ungueltige Randbedingung
+ if (CondT==sal_False) {
+ T[0]=0.0;
+ for (i=0;i<n;i++) {
+ deltX=x[i+1]-x[i]; deltY=y[i+1]-y[i];
+ delt =deltX*deltX+deltY*deltY;
+ if (delt<=0.0) return 3; // zwei identische Punkte nacheinander!
+ T[i+1]=T[i]+sqrt(delt);
+ }
+ }
+ switch (MargCond) {
+ case 0: break;
+ case 1: case 2: {
+ alphX=Marg01; betX=MargN1;
+ alphY=Marg02; betY=MargN2;
+ } break;
+ case 3: {
+ if (x[n]!=x[0]) return 3;
+ if (y[n]!=y[0]) return 4;
+ } break;
+ case 4: {
+ if (abs(Marg01)>=MAXROOT) {
+ alphX=0.0;
+ alphY=sign(1.0,y[1]-y[0]);
+ } else {
+ alphX=sign(sqrt(1.0/(1.0+Marg01*Marg01)),x[1]-x[0]);
+ alphY=alphX*Marg01;
+ }
+ if (abs(MargN1)>=MAXROOT) {
+ betX=0.0;
+ betY=sign(1.0,y[n]-y[n-1]);
+ } else {
+ betX=sign(sqrt(1.0/(1.0+MargN1*MargN1)),x[n]-x[n-1]);
+ betY=betX*MargN1;
+ }
+ }
+ } // switch MargCond
+ if (MargCond==3) {
+ Error=PeriodicSpline(n,T,x,bx,cx,dx);
+ if (Error!=0) return(Error+4);
+ Error=PeriodicSpline(n,T,y,by,cy,dy);
+ if (Error!=0) return(Error+10);
+ } else {
+ Error=NaturalSpline(n,T,x,alphX,betX,MargCond,bx,cx,dx);
+ if (Error!=0) return(Error+4);
+ Error=NaturalSpline(n,T,y,alphY,betY,MargCond,by,cy,dy);
+ if (Error!=0) return(Error+9);
+ }
+ return 0;
+}
+
+
+
+/*************************************************************************
+|*
+|* CalcSpline()
+|*
+|* Beschreibung Berechnet die Koeffizienten eines parametrischen
+|* natuerlichen oder periodischen kubischen
+|* Polynomsplines. Die Eckpunkte des uebergebenen
+|* Polygons werden als Stuetzstellen angenommen.
+|* n liefert die Anzahl der Teilpolynome.
+|* Ist die Berechnung fehlerfrei verlaufen, so
+|* liefert die Funktion sal_True. Nur in diesem Fall
+|* ist Speicher fuer die Koeffizientenarrays
+|* allokiert, der dann spaeter vom Aufrufer mittels
+|* delete freizugeben ist.
+|*
+*************************************************************************/
+
+sal_Bool CalcSpline(Polygon& rPoly, sal_Bool Periodic, sal_uInt16& n,
+ double*& ax, double*& ay, double*& bx, double*& by,
+ double*& cx, double*& cy, double*& dx, double*& dy, double*& T)
+{
+ sal_uInt8 Marg;
+ double Marg01;
+ double MargN1,MargN2;
+ sal_uInt16 i;
+ Point P0(-32768,-32768);
+ Point Pt;
+
+ n=rPoly.GetSize();
+ ax=new double[rPoly.GetSize()+2];
+ ay=new double[rPoly.GetSize()+2];
+
+ n=0;
+ for (i=0;i<rPoly.GetSize();i++) {
+ Pt=rPoly.GetPoint(i);
+ if (i==0 || Pt!=P0) {
+ ax[n]=Pt.X();
+ ay[n]=Pt.Y();
+ n++;
+ P0=Pt;
+ }
+ }
+
+ if (Periodic) {
+ Marg=3;
+ ax[n]=ax[0];
+ ay[n]=ay[0];
+ n++;
+ } else {
+ Marg=2;
+ }
+
+ bx=new double[n+1];
+ by=new double[n+1];
+ cx=new double[n+1];
+ cy=new double[n+1];
+ dx=new double[n+1];
+ dy=new double[n+1];
+ T =new double[n+1];
+
+ Marg01=0.0;
+ MargN1=0.0;
+ MargN2=0.0;
+ if (n>0) n--; // n Korregieren (Anzahl der Teilpolynome)
+
+ sal_Bool bRet = sal_False;
+ if ( ( Marg == 3 && n >= 3 ) || ( Marg == 2 && n >= 2 ) )
+ {
+ bRet = ParaSpline(n,ax,ay,Marg,Marg01,Marg01,MargN1,MargN2,sal_False,T,bx,cx,dx,by,cy,dy) == 0;
+ }
+ if ( bRet == sal_False )
+ {
+ delete[] ax;
+ delete[] ay;
+ delete[] bx;
+ delete[] by;
+ delete[] cx;
+ delete[] cy;
+ delete[] dx;
+ delete[] dy;
+ delete[] T;
+ n=0;
+ }
+ return bRet;
+}
+
+
+/*************************************************************************
+|*
+|* Spline2Poly()
+|*
+|* Beschreibung Konvertiert einen parametrichen kubischen
+|* Polynomspline Spline (natuerlich oder periodisch)
+|* in ein angenaehertes Polygon.
+|* Die Funktion liefert sal_False, wenn ein Fehler bei
+|* der Koeffizientenberechnung aufgetreten ist oder
+|* das Polygon zu gross wird (>PolyMax=16380). Im 1.
+|* Fall hat das Polygon 0, im 2. Fall PolyMax Punkte.
+|* Um Koordinatenueberlaeufe zu vermeiden werden diese
+|* auf +/-32000 begrenzt.
+|*
+*************************************************************************/
+sal_Bool Spline2Poly(Polygon& rSpln, sal_Bool Periodic, Polygon& rPoly)
+{
+ short MinKoord=-32000; // zur Vermeidung
+ short MaxKoord=32000; // von Ueberlaeufen
+
+ double* ax; // Koeffizienten der Polynome
+ double* ay;
+ double* bx;
+ double* by;
+ double* cx;
+ double* cy;
+ double* dx;
+ double* dy;
+ double* tv;
+
+ double Step; // Schrittweite fuer t
+ double dt1,dt2,dt3; // Delta t, y, ^3
+ double t;
+ sal_Bool bEnde; // Teilpolynom zu Ende?
+ sal_uInt16 n; // Anzahl der zu zeichnenden Teilpolynome
+ sal_uInt16 i; // aktuelles Teilpolynom
+ sal_Bool bOk; // noch alles ok?
+ sal_uInt16 PolyMax=16380;// Maximale Anzahl von Polygonpunkten
+ long x,y;
+
+ bOk=CalcSpline(rSpln,Periodic,n,ax,ay,bx,by,cx,cy,dx,dy,tv);
+ if (bOk) {
+ Step =10;
+
+ rPoly.SetSize(1);
+ rPoly.SetPoint(Point(short(ax[0]),short(ay[0])),0); // erster Punkt
+ i=0;
+ while (i<n) { // n Teilpolynome malen
+ t=tv[i]+Step;
+ bEnde=sal_False;
+ while (!bEnde) { // ein Teilpolynom interpolieren
+ bEnde=t>=tv[i+1];
+ if (bEnde) t=tv[i+1];
+ dt1=t-tv[i]; dt2=dt1*dt1; dt3=dt2*dt1;
+ x=long(ax[i]+bx[i]*dt1+cx[i]*dt2+dx[i]*dt3);
+ y=long(ay[i]+by[i]*dt1+cy[i]*dt2+dy[i]*dt3);
+ if (x<MinKoord) x=MinKoord; if (x>MaxKoord) x=MaxKoord;
+ if (y<MinKoord) y=MinKoord; if (y>MaxKoord) y=MaxKoord;
+ if (rPoly.GetSize()<PolyMax) {
+ rPoly.SetSize(rPoly.GetSize()+1);
+ rPoly.SetPoint(Point(short(x),short(y)),rPoly.GetSize()-1);
+ } else {
+ bOk=sal_False; // Fehler: Polygon wird zu gross
+ }
+ t=t+Step;
+ } // Ende von Teilpolynom
+ i++; // naechstes Teilpolynom
+ }
+ delete[] ax;
+ delete[] ay;
+ delete[] bx;
+ delete[] by;
+ delete[] cx;
+ delete[] cy;
+ delete[] dx;
+ delete[] dy;
+ delete[] tv;
+ return bOk;
+ } // Ende von if (bOk)
+ rPoly.SetSize(0);
+ return sal_False;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgvspln.hxx b/vcl/source/filter/sgvspln.hxx
new file mode 100644
index 000000000000..93c08ab62883
--- /dev/null
+++ b/vcl/source/filter/sgvspln.hxx
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _SGVSPLN_HXX
+#define _SGVSPLN_HXX
+
+/*************************************************************************
+|*
+|* CalcSpline()
+|*
+|* Beschreibung Berechnet die Koeffizienten eines parametrischen
+|* natrlichen oder periodischen kubischen
+|* Polynomsplines. Die Eckpunkte des šbergebenen
+|* Polygons werden als Sttzstellen angenommen.
+|* n liefert die Anzahl der Teilpolynome.
+|* Ist die Berechnung fehlerfrei verlaufen, so
+|* liefert die Funktion sal_True. Nur in diesem Fall
+|* ist Speicher fr die Koeffizientenarrays
+|* allokiert, der dann sp„ter vom Aufrufer mittels
+|* delete freizugeben ist.
+|*
+*************************************************************************/
+
+sal_Bool CalcSpline(Polygon& rPoly, sal_Bool Periodic, sal_uInt16& n,
+ double*& ax, double*& ay, double*& bx, double*& by,
+ double*& cx, double*& cy, double*& dx, double*& dy, double*& T);
+
+/*************************************************************************
+|*
+|* Poly2Spline()
+|*
+|* Beschreibung Konvertiert einen parametrichen kubischen
+|* Polynomspline Spline (natrlich oder periodisch)
+|* in ein angen„hertes Polygon.
+|* Die Funktion liefert sal_False, wenn ein Fehler bei
+|* der Koeffizientenberechnung aufgetreten ist oder
+|* das Polygon zu gro?wird (>PolyMax=16380). Im 1.
+|* Fall hat das Polygon 0, im 2. Fall PolyMax Punkte.
+|* Um Koordinatenberl„ufe zu vermeiden werden diese
+|* auf +/-32000 begrenzt.
+|*
+*************************************************************************/
+sal_Bool Spline2Poly(Polygon& rSpln, sal_Bool Periodic, Polygon& rPoly);
+
+#endif //_SGVSPLN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/sgvtext.cxx b/vcl/source/filter/sgvtext.cxx
new file mode 100644
index 000000000000..235f36808298
--- /dev/null
+++ b/vcl/source/filter/sgvtext.cxx
@@ -0,0 +1,1277 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <rtl/math.h>
+#include <comphelper/string.hxx>
+#include <tools/config.hxx>
+#include <svtools/filter.hxx>
+#include "sgffilt.hxx"
+#include "sgfbram.hxx"
+#include "sgvmain.hxx"
+
+extern SgfFontLst* pSgfFonts;
+
+#ifndef abs
+#define abs(x) ((x)<0 ? -(x) : (x))
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Einschraenkungen: Schatten nur grau, 2D und mit fixem Abstand.
+//
+//
+//
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// AbsBase.Pas
+
+// die folgenden Werte sind in % vom maximalen Schriftgrad der Zeile */
+#define UndlSpace 5 /* Untersteichungsabstand von der Baseline */
+#define UndlWidth 6 /* Untersteichungsdicke */
+#define UndlSpac2 7 /* Zwischenraum bei doppelter Unterstreichung */
+#define StrkSpace 25 /* Abstand der Durchstreichlinie von der Baseline*/
+#define StrkWidth 5 /* Durchstreichungsliniendicke */
+#define StrkSpac2 7 /* Zwischenraum bei doppelter Durchstreichung */
+#define OutlWidth 2 /* Strichstaerke ist 2% vom Schriftgrad */
+
+// vvv Sonderzeichen im TextBuffer vvv
+#define TextEnd 0 /* ^@ Ende der Zeichenkette */
+#define HardSpace 6 /* ^F Hartspace (wird nicht umbrochen) ,' ' */
+#define GrafText 7 /* ^G Im Text eingebundene Grafik (future) */
+#define Tabulator 9 /* ^I Tabulatorzeichen, Pfeil */
+#define LineFeed 10 /* ^J Neue Zeile */
+#define SoftTrennK 11 /* ^K Zeichen fuer k-c-Austausch bei Trennung, 'k' */
+#define AbsatzEnd 13 /* ^M Neuer Absatz =CR */
+#define HardTrenn 16 /* ^P Hartes Trennzeichen (wird nicht umbrochen), '-' */
+#define SoftTrennAdd 19 /* ^S Zusatz-Zeichen Trennung von z.b."Schiff-fahrt" */
+#define Paragraf 21 /* ^U Zeichen welches fuer Paragraf-Zeichen */
+#define Escape 27 /* ^[ Escapesequenz einleiten */
+#define SoftTrenn 31 /* ^_ Weiches Trennzeichen, '-' nur Zeilenende */
+#define MaxEscValLen 8
+#define MaxEscLen (MaxEscValLen+3)
+
+//==============================================================================
+// Escapesequenzen: [Esc]<Ident><Value>[Esc] also mind. 4 Char
+// Max. Laenge von Value soll sein: 8 Char (7+Vorzeichen). Demnach max. Laenge
+// einer Escapesequenz: 11 Char.
+// Identifer:
+
+#define EscFont 'F' /* FontID, z.B. 92500 fuer CG Times */
+#define EscGrad 'G' /* Schriftgrad 1..255 fuer <<Pt-127<<Pt */
+#define EscBreit 'B' /* Breite 1..255% des Schriftgrades */
+#define EscKaptS 'K' /* Kapitaelchengroesse 1..255% des Schriftgrades */
+#define EscLFeed 'L' /* Zeilenabstand 1..32767% vom max. Schriftgrad der Zeile */
+ // oder 1..32767 fuer 1..16383<<Pt absolut (Wenn Bit 15=1)
+#define EscSlant 'S' /* Kursiv(Winkel) 1..8999 fuer 0.01deg..89.99deg */
+#define EscVPos 'V' /* Zeichen Vertikal-Position 1..255 fuer <<Pt..127<<Pt */
+#define EscZAbst 'Z' /* Zeichenabstand -128..127% */
+#define EscHJust 'A' /* H-Justify Absatz: Links, Zentr, Rechts, Block, Austreibend, Gesperrt (0..5)*/
+
+#define EscFarbe 'C' /* Farbe 0..7 */
+#define EscBFarb 'U' /* BackFarbe 0..7 */
+#define EscInts 'I' /* Farbintensitaet 0..100% */
+#define EscMustr 'M' /* Muster 0..? inkl. Transp... */
+#define EscMFarb 'O' /* Musterfarbe 0..7 */
+#define EscMBFrb 'P' /* 2. Musterfarbe 0..7 */
+#define EscMInts 'W' /* Musterintensitaet 0..7 */
+
+#define EscSMstr 'E' /* Schattenmuster 0..? inkl. Transp... */
+#define EscSFarb 'R' /* Schattenfarbe 0..7 */
+#define EscSBFrb 'T' /* 2. Schattenfarbe 0..7 */
+#define EscSInts 'Q' /* Schattenintensitaet 0..7 */
+
+#define EscSXDst 'X' /* Schattenversatz X 0..100% */
+#define EscSYDst 'Y' /* Schattenversatz Y 0..100% */
+#define EscSDist 'D' /* Schattenversatz X-Y 0..100% */
+
+#define EscBold 'f' /* Fett */
+#define EscLSlnt 'l' /* LKursiv */
+#define EscRSlnt 'r' /* RKursiv */
+#define EscUndln 'u' /* Unterstrichen */
+#define EscDbUnd 'p' /* doppelt Unterstrichen */
+#define EscKaptF 'k' /* Kapitaelchenflag */
+#define EscStrik 'd' /* Durchgestrichen */
+#define EscDbStk 'e' /* doppelt Durchgestrichen */
+#define EscSupSc 'h' /* Hochgestellt */
+#define EscSubSc 't' /* Tiefgestellt */
+#define Esc2DShd 's' /* 2D-Schatten */
+#define Esc3DShd 'j' /* 3D-Schatten */
+#define Esc4DShd 'i' /* 4D-Schatten */
+#define EscEbShd 'b' /* Embossed */
+
+// AllEscIdent =[EscFont, EscGrad, EscBreit,EscKaptS,EscLFeed,EscSlant,EscVPos, EscZAbst,EscHJust,
+// EscFarbe,EscBFarb,EscInts, EscMustr,EscMFarb,EscMBFrb,EscMInts,
+// EscSMstr,EscSFarb,EscSBFrb,EscSInts,EscSXDst,EscSYDst,EscSDist,
+// EscBold, EscLSlnt,EscRSlnt,EscUndln,EscDbUnd,EscKaptF,EscStrik,EscDbStk,
+// EscSupSc,EscSubSc,Esc2DShd,Esc3DShd,Esc4DShd];
+// Justify muss spaetestens am Anfang des Absatzes stehen
+#define EscSet '\x1e' /* Flag setzen */
+#define EscReset '\x1f' /* Flag loeschen */
+#define EscDeflt '\x11' /* Flag auf default setzen */
+#define EscToggl '\x1d' /* Flag Toggeln */
+#define EscNoFlg 0
+#define EscNoVal -2147483647 /* -MaxLongInt */
+//==============================================================================
+#define NoTrenn 0xFFFF /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn auf keinen Fall getrennt werden soll */
+#define DoTrenn 0xFFFE /* Wert fuer Parameter 'Rest' von GetTextChar(), wenn getrennt werden soll */
+
+#define MaxLineChars 1024
+
+#define ChrXPosArrSize (MaxLineChars+1+1) /* 2k - Beginnt mit 0 im gegensatz zu StarDraw */
+#define CharLineSize (MaxLineChars+1+1)
+
+#define MinChar 32
+#define MaxChar 255
+
+
+//==============================================================================
+
+#define GradDiv 2
+#define CharTopToBase 100 /* wegen Apostrophe und Umlaute mehr als 75% */
+#define CharTopToBtm 120 /* Zeilenhoehe ist groesser als Schriftgrad */
+ // bei Avanti-Bold 'ue' eigentlich sogar 130%
+
+// end of AbsBase.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// DefBase.Pas
+
+#define TextBoldBit 0x0001 /* Fett */
+#define TextRSlnBit 0x0002 /* Kursiv */
+#define TextUndlBit 0x0004 /* Unterstrichen */
+#define TextStrkBit 0x0008 /* Durchgesteichen */
+#define TextSupSBit 0x0010 /* Hocgestellt */
+#define TextSubSBit 0x0020 /* Tiefgestellt */
+#define TextKaptBit 0x0040 /* Kapitaelchen */
+#define TextLSlnBit 0x0080 /* Linkskursiv */
+#define TextDbUnBit 0x0100 /* Doppelt unterstrichen */
+#define TextDbStBit 0x0200 /* Doppelt durchgestrichen */
+#define TextSh2DBit 0x0400 /* 2D-Schatten 2.0 */
+#define TextSh3DBit 0x0800 /* 3D-Schatten 2.0 */
+#define TextSh4DBit 0x1000 /* 4D-Schatten 2.0 */
+#define TextShEbBit 0x2000 /* Embossed-Schatten 2.0 */
+#define FontAtrBits (TextBoldBit | TextRSlnBit)
+
+#define THJustLeft 0x00
+#define THJustCenter 0x01
+#define THJustRight 0x02
+#define THJustBlock 0x03
+#define THJustDrvOut 0x04 /* Austreibend Formatiert */
+#define THJustLocked 0x05 /* A l s S p e r r s c h r i f t */
+#define TVJustTop 0x00 /* Future */
+#define TVJustCenter 0x10 /* Future */
+#define TVJustBottom 0x20 /* Future */
+#define TVJustBlock 0x30 /* Future */
+
+#define MaxCharSlant 4200 /* Maximal 42deg kursiv ! */
+
+// end of DefBase.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+
+sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L);
+
+sal_Bool CheckTextOutl(ObjAreaType& F, ObjLineType& L)
+{
+ return (F.FIntens!=L.LIntens) ||
+ ((F.FFarbe!=L.LFarbe) && (F.FIntens>0)) ||
+ ((F.FBFarbe!=L.LBFarbe) && (F.FIntens<100));
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// Misc.Pas
+
+short hPoint2Sgf(short a)
+{
+ long b;
+ b=long(a)*127*SgfDpmm/(144*5);
+ return short(b);
+}
+
+// End of Misc.Pas
+// AbsRead.Pas
+
+// ======================================================================
+// Function GetTopToBaseLine() Function GetBaseLineToBtm()
+//
+// Abstand von Zeilenoberkante bis BaseLine bzw. von BaseLine bis
+// Unterkante berechnen. Alles in SGF-Units.
+// ======================================================================
+
+sal_uInt16 GetTopToBaseLine(sal_uInt16 MaxGrad)
+{
+ long ret;
+ ret=long(MaxGrad)*long(CharTopToBase) /long(100);
+ return sal_uInt16(ret);
+}
+
+// ======================================================================
+// Function GetTextChar() Function GetTextCharConv()
+//
+// Liest ein Zeichen aus dem Textbuffer, wertet dabei eventuell
+// auftretende Escapesequenzen aus und setzt dementsprechend den
+// Ein-/Ausgabeparameter AktAtr. Index wird entsprechend erhoeht.
+// Der Parameter Rest muss immer die Anzahl der Zeichen beinhalten,
+// den angeforderten Zeichen in der aktuellen Zeile noch folgen.
+// Ansonsten funktioniert die Silbentrennung nicht richtig. Gibt man
+// stattdessen die Konstante NoTrenn an, wird in keinem Fall
+// getrennt, die Konstante DoTrenn bewirkt dagegen, dass ueberall dort
+// getrennt wird, wo ein SoftTrenner vorkommt.
+//
+// SoftTrenner werden immer in ein Minuszeichen konvertiert.
+// GetTextCharConv() konvertiert zusaetzlich HardSpace und AbsatzEnde
+// in Spaces sowie HardTrenner in Minuszeichen. TextEnde wird immer
+// als Char(0) geliefert.
+// ======================================================================
+
+
+
+UCHAR ConvertTextChar(UCHAR c)
+{
+ if (c<32) {
+ switch (c) {
+ case HardSpace : c=' '; break;
+ case AbsatzEnd : c=' '; break;
+ case SoftTrenn : c='-'; break;
+ case HardTrenn : c='-'; break;
+ case SoftTrennK : c='-'; break;
+ case SoftTrennAdd: c='-';
+ }
+ }
+ return c;
+}
+
+long ChgValue(long Def, long Min, long Max, UCHAR FlgVal, long NumVal)
+{
+ long r=0;
+
+ if (FlgVal==EscDeflt) {
+ r=Def; // zurueck auf Default
+ } else {
+ if (NumVal!=EscNoVal) r=NumVal; // Hart setzen
+ }
+
+ if (Min!=0 || Max!=0) {
+ if (r>Max) r=Max;
+ if (r<Min) r=Min;
+ }
+ return r;
+}
+
+
+
+void ChgSchnittBit(sal_uInt16 Bit, sal_uInt16 Radio1, sal_uInt16 Radio2, sal_uInt16 Radio3,
+ UCHAR FlgVal, sal_uInt16 Schnitt0, sal_uInt16& Schnitt)
+{
+ sal_uInt16 All,Rad;
+
+ Rad=Radio1 | Radio2 | Radio3;
+ All=Bit | Rad;
+
+ switch (FlgVal) {
+ case EscSet : Schnitt=(Schnitt & ~All) | Bit; break;
+ case EscReset: Schnitt=(Schnitt & ~All); break;
+ case EscDeflt: Schnitt=(Schnitt & ~All) | (Schnitt0 & All); break;
+ case EscToggl: Schnitt=(Schnitt & ~Rad) ^ Bit;
+ }
+}
+
+
+
+UCHAR GetNextChar(UCHAR* TBuf, sal_uInt16 Index)
+{
+ sal_uInt16 Cnt;
+ while (TBuf[Index]==Escape) {
+ Index++;
+ Cnt=0;
+ while (TBuf[Index]!=Escape && Cnt<=MaxEscLen) {
+ Index++; Cnt++; }
+ Index++;
+ }
+ return TBuf[Index];
+}
+
+
+
+UCHAR ProcessOne(UCHAR* TBuf, sal_uInt16& Index,
+ ObjTextType& Atr0, ObjTextType& AktAtr,
+ sal_Bool ScanEsc)
+{
+ UCHAR c;
+ UCHAR Ident;
+ sal_Bool Ende;
+ sal_Bool q;
+ UCHAR FlgVal;
+ long NumVal;
+ long Sgn;
+ short i;
+ sal_Bool EoVal;
+
+ do {
+ c=TBuf[Index]; Index++;
+ Ende=(c!=Escape);
+ if (Ende==sal_False) {
+ c=TBuf[Index]; Index++;
+ Ident=c; // Identifer merken
+ FlgVal=EscNoFlg;
+ NumVal=EscNoVal;
+ c=TBuf[Index]; Index++; // Hier faengt der Wert an
+ if (c==EscSet || c==EscReset || c==EscDeflt || c==EscToggl) FlgVal=c; else {
+ if (c=='-') Sgn=-1; else Sgn=1;
+ if (c=='+' || c=='-') { c=TBuf[Index]; Index++; }
+ i=MaxEscValLen;
+ NumVal=0;
+ do {
+ NumVal=10*NumVal+c-'0';
+ EoVal=(TBuf[Index]<'0' || TBuf[Index]>'9');
+ if (EoVal==sal_False) { c=TBuf[Index]; Index++; }
+ i--;
+ } while (i>0 && EoVal==sal_False);
+ NumVal=Sgn*NumVal;
+ }
+ q=!CheckTextOutl(AktAtr.F,AktAtr.L);
+
+ switch (Ident) {
+ case EscFont : AktAtr.SetFont(sal_uLong (ChgValue(Atr0.GetFont(),0,0 ,FlgVal,NumVal)));break;
+ case EscGrad : AktAtr.Grad =sal_uInt16(ChgValue(Atr0.Grad, 2,2000 ,FlgVal,NumVal)); break;
+ case EscBreit: AktAtr.Breite =sal_uInt16(ChgValue(Atr0.Breite, 1,1000 ,FlgVal,NumVal)); break;
+ case EscKaptS: AktAtr.Kapit =(sal_uInt8)(ChgValue(Atr0.Kapit, 1,255 ,FlgVal,NumVal)); break;
+ case EscLFeed: AktAtr.LnFeed =sal_uInt16(ChgValue(Atr0.LnFeed, 1,65535 ,FlgVal,NumVal)); break;
+ case EscSlant: AktAtr.Slant =sal_uInt16(ChgValue(Atr0.Slant, 1,MaxCharSlant ,FlgVal,NumVal)); break;
+ case EscVPos : AktAtr.ChrVPos=char (ChgValue(Atr0.ChrVPos,-128,127 ,FlgVal,NumVal)); break;
+ case EscZAbst: AktAtr.ZAbst =(sal_uInt8)(ChgValue(Atr0.ZAbst, 1,255 ,FlgVal,NumVal)); break;
+ case EscHJust: AktAtr.Justify=(sal_uInt8)(ChgValue(Atr0.Justify & 0x0F,0,5 ,FlgVal,NumVal)); break;
+ case EscFarbe: { AktAtr.L.LFarbe =(sal_uInt8)(ChgValue(Atr0.L.LFarbe,0,7 ,FlgVal,NumVal)); if (q) AktAtr.F.FFarbe =AktAtr.L.LFarbe; } break;
+ case EscBFarb: { AktAtr.L.LBFarbe=(sal_uInt8)(ChgValue(Atr0.L.LBFarbe,0,255,FlgVal,NumVal)); if (q) AktAtr.F.FBFarbe=AktAtr.L.LBFarbe; } break;
+ case EscInts : { AktAtr.L.LIntens=(sal_uInt8)(ChgValue(Atr0.L.LIntens,0,100,FlgVal,NumVal)); if (q) AktAtr.F.FIntens=AktAtr.L.LIntens; } break;
+
+ case EscMustr: { AktAtr.F.FMuster=sal_uInt16(ChgValue(Atr0.F.FMuster,0,65535,FlgVal,NumVal)); } break;
+ case EscMFarb: { AktAtr.F.FFarbe =(sal_uInt8)(ChgValue(Atr0.F.FFarbe,0,7 ,FlgVal,NumVal)); } break;
+ case EscMBFrb: { AktAtr.F.FBFarbe=(sal_uInt8)(ChgValue(Atr0.F.FBFarbe,0,255,FlgVal,NumVal)); } break;
+ case EscMInts: { AktAtr.F.FIntens=(sal_uInt8)(ChgValue(Atr0.F.FIntens,0,100,FlgVal,NumVal)); } break;
+
+ case EscSMstr: { AktAtr.ShdF.FMuster=sal_uInt16(ChgValue(Atr0.ShdF.FMuster,0,65535,FlgVal,NumVal)); } break;
+ case EscSFarb: { AktAtr.ShdL.LFarbe =(sal_uInt8)(ChgValue(Atr0.ShdL.LFarbe,0,7 ,FlgVal,NumVal)); AktAtr.ShdF.FFarbe =AktAtr.ShdL.LFarbe; } break;
+ case EscSBFrb: { AktAtr.ShdL.LBFarbe=(sal_uInt8)(ChgValue(Atr0.ShdL.LBFarbe,0,255,FlgVal,NumVal)); AktAtr.ShdF.FBFarbe=AktAtr.ShdL.LBFarbe; } break;
+ case EscSInts: { AktAtr.ShdL.LIntens=(sal_uInt8)(ChgValue(Atr0.ShdL.LIntens,0,100,FlgVal,NumVal)); AktAtr.ShdF.FIntens=AktAtr.ShdL.LIntens; } break;
+ case EscSDist: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); AktAtr.ShdVers.y=AktAtr.ShdVers.x; } break;
+ case EscSXDst: { AktAtr.ShdVers.x=(short)ChgValue(Atr0.ShdVers.x,0,30000,FlgVal,NumVal); } break;
+ case EscSYDst: { AktAtr.ShdVers.y=(short)ChgValue(Atr0.ShdVers.y,0,30000,FlgVal,NumVal); } break;
+
+ case EscBold : ChgSchnittBit(TextBoldBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscRSlnt: ChgSchnittBit(TextRSlnBit,TextLSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscUndln: ChgSchnittBit(TextUndlBit,TextDbUnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscStrik: ChgSchnittBit(TextStrkBit,TextDbStBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscDbUnd: ChgSchnittBit(TextDbUnBit,TextUndlBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscDbStk: ChgSchnittBit(TextDbStBit,TextStrkBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscSupSc: ChgSchnittBit(TextSupSBit,TextSubSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscSubSc: ChgSchnittBit(TextSubSBit,TextSupSBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscKaptF: ChgSchnittBit(TextKaptBit,0,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscLSlnt: ChgSchnittBit(TextLSlnBit,TextRSlnBit,0,0 ,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case Esc2DShd: ChgSchnittBit(TextSh2DBit,TextSh3DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case Esc3DShd: ChgSchnittBit(TextSh3DBit,TextSh2DBit,TextSh4DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case Esc4DShd: ChgSchnittBit(TextSh4DBit,TextSh2DBit,TextSh3DBit,TextShEbBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ case EscEbShd: ChgSchnittBit(TextShEbBit,TextSh2DBit,TextSh3DBit,TextSh4DBit,FlgVal,Atr0.Schnitt,AktAtr.Schnitt); break;
+ } //endcase
+ if (TBuf[Index]==Escape) Index++; // zweites Esc weglesen }
+ } // if Ende==sal_False
+ } while (Ende==sal_False && ScanEsc==sal_False);
+ if (Ende==sal_False) c=Escape;
+ return c;
+} // end of ProcessOne
+
+
+UCHAR GetTextChar(UCHAR* TBuf, sal_uInt16& Index,
+ ObjTextType& Atr0, ObjTextType& AktAtr,
+ sal_uInt16 Rest, sal_Bool ScanEsc)
+{
+ UCHAR c,c0,nc;
+
+ c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc);
+ if (ScanEsc==sal_False) {
+ if (c==SoftTrennAdd || c==SoftTrennK || c==SoftTrenn) {
+ nc=GetNextChar(TBuf,Index);
+ c0=c;
+ if (Rest==0 || Rest==DoTrenn ||
+ nc==' ' || nc==AbsatzEnd || nc==TextEnd) c='-';
+ else {
+ c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // den Trenner ueberspringen
+ if (c0==SoftTrennAdd) {
+ if (c>=32) c=ProcessOne(TBuf,Index,Atr0,AktAtr,ScanEsc); // und hier noch 'nen Buchstaben ueberspringen
+ }
+ }
+ }
+ if ((Rest==1 || Rest==DoTrenn) && GetNextChar(TBuf,Index)==SoftTrennK) {
+ if (c=='c') c='k';
+ else if (c=='C') c='K';
+ }
+ }
+ return c;
+}
+
+ // HardSpace und HardTrenn muessen explizit konvertiert werden ! }
+ // if AktAtr.Schnitt and TextKaptBit =TextKaptBit then c:=UpCase(c);(explizit) }
+
+ // Bei der Trennmethode SoftTrennAdd wird davon ausgegangen, dass der zu }
+ // trennende Konsonant bereits 3x mal im TextBuf vorhanden ist, z.b.: }
+ // "Schiff-fahrt". Wenn nicht getrennt, dann wird "-f" entfernt. }
+
+
+
+UCHAR GetTextCharConv(UCHAR* TBuf, sal_uInt16& Index,
+ ObjTextType& Atr0, ObjTextType& AktAtr,
+ sal_uInt16 Rest, sal_Bool ScanEsc)
+{
+ UCHAR c;
+
+ c=GetTextChar(TBuf,Index,Atr0,AktAtr,Rest,ScanEsc);
+ if (c<32) {
+ switch (c) {
+ case HardSpace : c=' '; break;
+ case AbsatzEnd : c=' '; break;
+ case HardTrenn : c='-';
+ }
+ }
+ return c;
+}
+
+
+// ======================================================================
+// Function GetLineFeed()
+//
+// Benoetigter Zeilenabstand in SGF-Units. ChrVPos wird beruecksichtigt.
+// ======================================================================
+sal_uInt16 GetLineFeed(UCHAR* TBuf, sal_uInt16 Index, ObjTextType Atr0, ObjTextType AktAtr,
+ sal_uInt16 nChar, sal_uInt16& LF, sal_uInt16& MaxGrad)
+{
+ UCHAR c=0;
+ sal_Bool AbsEnd=sal_False;
+ sal_uLong LF100=0;
+ sal_uLong MaxLF100=0;
+ sal_Bool LFauto=0;
+ sal_Bool First=sal_True;
+ sal_uInt16 Grad;
+ sal_uInt16 i=0;
+ sal_uInt16 r=1;
+
+ MaxGrad=0;
+ while (!AbsEnd && nChar>0) {
+ nChar--;
+ c=GetTextChar(TBuf,Index,Atr0,AktAtr,nChar,sal_False);
+ i++;
+ AbsEnd=(c==TextEnd || c==AbsatzEnd);
+ if (First || (!AbsEnd && c!=' ' && c!=HardTrenn)) {
+ LFauto=(AktAtr.LnFeed & 0x8000)==0;
+ LF100=AktAtr.LnFeed & 0x7FFF;
+ if (LFauto) LF100=LF100*AktAtr.Grad; else LF100*=LF100;
+ if (AktAtr.ChrVPos>0) LF100-=AktAtr.ChrVPos*100;
+ if (LF100>MaxLF100) MaxLF100=LF100;
+ Grad=AktAtr.Grad;
+ if (AktAtr.ChrVPos>0) Grad=Grad-AktAtr.ChrVPos;
+ if (Grad>MaxGrad) MaxGrad=Grad;
+ First=sal_False;
+ }
+ if (!AbsEnd && c!=' ') r=i;
+ }
+ MaxGrad=hPoint2Sgf(MaxGrad);
+ if (MaxLF100<=4000) { // sonst Overflowgefahr
+ LF=sal_uInt16(hPoint2Sgf(short(MaxLF100)) /100);
+ } else {
+ LF=sal_uInt16(hPoint2Sgf(short(MaxLF100) /100));
+ }
+
+ return r;
+}
+
+// End of AbsRead.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// iFont.Pas
+
+#define DefaultSlant 1500 /* Default: Italic ist 15deg */
+#define SuperSubFact 60 /* SuperScript/SubScript: 60% vom Schriftgrad */
+#define DefaultSpace 40 /* Default: Space ist 40% vom SchriftGrad */
+
+sal_uInt16 SetTextContext(OutputDevice& rOut, ObjTextType& Atr, sal_Bool Kapt, sal_uInt16 Dreh,
+ sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
+{
+ SgfFontOne* pSgfFont; // Font aus dem IniFile
+ Font aFont;
+ Color aColor;
+ sal_uLong Grad;
+ sal_uLong Brei;
+ String FNam;
+ sal_uInt16 StdBrei=50; // Durchschnittliche Zeichenbreite in % von Schriftgrad
+ sal_Bool bFit=(FitXMul!=1 || FitXDiv!=1 || FitYMul!=1 || FitYDiv!=1);
+
+ pSgfFont = pSgfFonts->GetFontDesc(Atr.GetFont());
+
+ if ( pSgfFont!=NULL )
+ {
+ FNam =pSgfFont->SVFName;
+ StdBrei=pSgfFont->SVWidth;
+ if (pSgfFont->Fixd) aFont.SetPitch(PITCH_FIXED); else aFont.SetPitch(PITCH_VARIABLE);
+ aFont.SetFamily(pSgfFont->SVFamil);
+ aFont.SetCharSet(pSgfFont->SVChSet);
+ aFont.SetName(FNam);
+ }
+ else
+ { // Falls nich im Inifile, sind hier einige Fonts hart kodiert
+ aFont.SetPitch(PITCH_VARIABLE);
+ switch (Atr.GetFont()) {
+ case 92500: case 92501: case 92504: case 92505:
+ {
+#if defined(WNT)
+ FNam=rtl::OUString("Times New Roman"); // CG Times ist unter Windows Times New Roman
+#else
+ FNam=rtl::OUString("Times"); // ansonsten ist das einfach Times
+#endif
+ StdBrei=40;
+ aFont.SetFamily(FAMILY_ROMAN);
+ } break;
+ case 94021: case 94022: case 94023: case 94024: {
+#if defined(WNT)
+ FNam=rtl::OUString("Arial"); // Univers ist unter Windows Arial
+#else
+ FNam=rtl::OUString("Helvetica"); // und ansonsten Helvetica
+#endif
+ aFont.SetFamily(FAMILY_SWISS);
+ StdBrei=47;
+ } break;
+ case 93950: case 93951: case 93952: case 93953: {
+#if defined(WNT)
+ FNam=rtl::OUString("Courier New"); // Der Vector-Courierfont unter Windows heisst Courier New
+#else
+ FNam=rtl::OUString("Courier"); // ansonsten ist und bleibt Courier immer Courier
+#endif
+ aFont.SetFamily(FAMILY_ROMAN);
+ aFont.SetPitch(PITCH_FIXED);
+ } break;
+ default: FNam = rtl::OUString("Helvetica");
+ }
+ aFont.SetName(FNam);
+ //aFont.SetCharSet(CHARSET_SYSTEM);
+ }
+
+ Grad=sal_uLong(Atr.Grad);
+ if ((Atr.Schnitt & TextKaptBit) !=0 && Kapt) Grad=Grad*sal_uLong(Atr.Kapit)/100;
+ if ((Atr.Schnitt & TextSupSBit) !=0 || (Atr.Schnitt & TextSubSBit) !=0) Grad=Grad*SuperSubFact/100;
+ Brei=Grad;
+ if (Atr.Breite!=100 || bFit) {
+ if (bFit) {
+ Grad=Grad*sal_uLong(FitYMul)/sal_uLong(FitYDiv);
+ Brei=Brei*sal_uLong(FitXMul)/sal_uLong(FitXDiv);
+ }
+ Brei=Brei*sal_uLong(Atr.Breite)/100;
+ Brei=Brei*sal_uLong(StdBrei)/100;
+ aFont.SetSize(Size(hPoint2Sgf(sal_uInt16(Brei)),hPoint2Sgf(sal_uInt16(Grad))));
+ } else {
+ aFont.SetSize(Size(0,hPoint2Sgf(sal_uInt16(Grad))));
+ }
+
+ aColor=Sgv2SvFarbe(Atr.L.LFarbe,Atr.L.LBFarbe,Atr.L.LIntens); aFont.SetColor(aColor);
+ aColor=Sgv2SvFarbe(Atr.F.FFarbe,Atr.F.FBFarbe,Atr.F.FIntens); aFont.SetFillColor(aColor);
+ aFont.SetTransparent(sal_True);
+ aFont.SetAlign(ALIGN_BASELINE);
+
+ Dreh/=10; Dreh=3600-Dreh; if (Dreh==3600) Dreh=0;
+ aFont.SetOrientation(Dreh);
+
+ if ((Atr.Schnitt & TextBoldBit) !=0) aFont.SetWeight(WEIGHT_BOLD);
+ if ((Atr.Schnitt & TextRSlnBit) !=0) aFont.SetItalic(ITALIC_NORMAL);
+ if ((Atr.Schnitt & TextUndlBit) !=0) aFont.SetUnderline(UNDERLINE_SINGLE);
+ if ((Atr.Schnitt & TextDbUnBit) !=0) aFont.SetUnderline(UNDERLINE_DOUBLE);
+ if ((Atr.Schnitt & TextStrkBit) !=0) aFont.SetStrikeout(STRIKEOUT_SINGLE);
+ if ((Atr.Schnitt & TextDbStBit) !=0) aFont.SetStrikeout(STRIKEOUT_DOUBLE);
+ if ((Atr.Schnitt & TextSh2DBit) !=0) aFont.SetShadow(sal_True);
+ if ((Atr.Schnitt & TextSh3DBit) !=0) aFont.SetShadow(sal_True);
+ if ((Atr.Schnitt & TextSh4DBit) !=0) aFont.SetShadow(sal_True);
+ if ((Atr.Schnitt & TextShEbBit) !=0) aFont.SetShadow(sal_True);
+ if (CheckTextOutl(Atr.F,Atr.L)) aFont.SetOutline(sal_True);
+
+ if (aFont!=rOut.GetFont()) rOut.SetFont(aFont);
+
+ return 0;
+}
+
+// iFont.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// Absatz.Pas
+
+struct ProcChrSta {
+ sal_uInt16 Index;
+ sal_uInt16 ChrXP;
+ UCHAR OutCh;
+ sal_Bool Kapt;
+ ObjTextType Attrib;
+};
+
+void InitProcessCharState(ProcChrSta& State, ObjTextType& AktAtr, sal_uInt16 IndexA)
+{
+ State.Attrib=AktAtr;
+ State.OutCh=0;
+ State.Index=IndexA;
+ State.ChrXP=0;
+ State.Kapt=sal_False;
+}
+
+sal_Bool UpcasePossible(UCHAR c)
+{
+ if ((c>='a' && c<='z') || c == 0xe4 || c == 0xf6 || c == 0xfc ) return sal_True;
+ else return sal_False;
+}
+
+UCHAR Upcase(UCHAR c)
+{
+ if ((c>=(UCHAR)'a' && c<=(UCHAR)'z')) c=(c-(UCHAR)'a')+(UCHAR)'A';
+ else if ( c == 0xe4 ) c = 0xc4;
+ else if ( c == 0xf6 ) c = 0xd6;
+ else if ( c == 0xfc ) c = 0xdc;
+ return c;
+}
+
+sal_uInt16 GetCharWidth(OutputDevice& rOut, UCHAR c)
+{
+ sal_uInt16 ChrWidth;
+
+ if (c==' ')
+ {
+ ChrWidth=(sal_uInt16)rOut.GetTextWidth( rtl::OUString('A') );
+ if (rOut.GetFont().GetPitch()!=PITCH_FIXED) {
+ ChrWidth=MulDiv(ChrWidth,DefaultSpace,100);
+ }
+ }
+ else
+ {
+ // with MaxChar == 255 c cannot be greater than MaxChar
+ // assert if MaxChar is ever changed
+ OSL_ENSURE( MaxChar == 255, "MaxChar not 255" );
+ OSL_ENSURE(sizeof(UCHAR) == 1, "should be 1");
+ if (c>=MinChar /*&& c<=MaxChar*/)
+ {
+ ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(reinterpret_cast<sal_Char*>(&c), 1, RTL_TEXTENCODING_IBM_437));
+ }
+ else
+ {
+ ChrWidth=(sal_uInt16)rOut.GetTextWidth(rtl::OUString(static_cast<sal_Unicode>('A')));
+ }
+ }
+ return ChrWidth;
+}
+
+UCHAR ProcessChar(OutputDevice& rOut, UCHAR* TBuf, ProcChrSta& R, ObjTextType& Atr0,
+ sal_uInt16& nChars, sal_uInt16 Rest,
+ short* Line, UCHAR* cLine)
+{
+ sal_uInt16 KernDist=0; // Wert fuer Kerning
+ sal_uInt16 ChrWidth;
+ UCHAR c;
+ UCHAR c1;
+ sal_Bool AbsEnd;
+
+ c=GetTextChar(TBuf,R.Index,Atr0,R.Attrib,Rest,sal_False); // versucht evtl. zu trennen, wenn Rest entsprechenden Wert besitzt
+
+ AbsEnd=(c==AbsatzEnd || c==TextEnd);
+ if (AbsEnd==sal_False) {
+ R.OutCh=ConvertTextChar(c); // von HardTrenn nach '-', ...
+ R.Kapt=(R.Attrib.Schnitt & TextKaptBit) !=0 && UpcasePossible(R.OutCh);
+ if (R.Kapt) R.OutCh=Upcase(R.OutCh);
+ SetTextContext(rOut,R.Attrib,R.Kapt,0,1,1,1,1);
+
+ if (R.Kapt) c1=Upcase(c); else c1=c;
+ ChrWidth=GetCharWidth(rOut,c1);
+
+ if (R.Attrib.ZAbst!=100) { // Spezial-Zeichenabstand ?
+ sal_uLong Temp;
+ Temp=sal_uLong(ChrWidth)*sal_uLong(R.Attrib.ZAbst)/100;
+ ChrWidth=sal_uInt16(Temp);
+ }
+ nChars++;
+ if (R.ChrXP>32000) R.ChrXP=32000;
+ Line[nChars]=R.ChrXP-KernDist;
+ cLine[nChars]=c;
+ R.ChrXP+=ChrWidth-KernDist; // Position fuer den naechsten Character
+ }
+ return c;
+}
+
+void FormatLine(UCHAR* TBuf, sal_uInt16& Index, ObjTextType& Atr0, ObjTextType& AktAtr,
+ sal_uInt16 UmbWdt, sal_uInt16 AdjWdt,
+ short* Line, sal_uInt16& nChars,
+ double, double,
+ UCHAR* cLine, sal_Bool TextFit)
+{
+ VirtualDevice vOut;
+ UCHAR c,c0;
+ UCHAR ct;
+ sal_Bool First; // erster Char ?
+ sal_uInt8 Just = 0; // Absatzformatierung
+ sal_Bool Border; // Rand der Box erreicht ?
+ sal_Bool Border0;
+ sal_Bool AbsEnd; // Ende des Absatzes erreicht ?
+ ProcChrSta* R=new ProcChrSta;
+ ProcChrSta* R0=new ProcChrSta;
+ ProcChrSta* WErec=new ProcChrSta;
+ sal_uInt16 WEnChar;
+ ProcChrSta* WErec0=new ProcChrSta;
+ sal_uInt16 WEnChar0;
+ ProcChrSta* TRrec=new ProcChrSta;
+ sal_uInt16 TRnChar;
+
+ sal_uInt16 WordEndCnt; // Justieren und Trennen
+ sal_Bool WordEnd;
+ sal_Bool Trenn;
+
+ short BoxRest; // zum Quetschen und formatieren
+ sal_uInt16 i,j,k,h;
+ sal_uInt16 re,li;
+
+ vOut.SetMapMode(MapMode(MAP_10TH_MM,Point(),Fraction(1,4),Fraction(1,4)));
+
+ nChars=0;
+ SetTextContext(vOut,AktAtr,sal_False,0,1,1,1,1);
+ InitProcessCharState(*R,AktAtr,Index);
+ (*R0)=(*R); (*WErec)=(*R); WEnChar=0; c0=0; Border0=sal_False;
+ Border=sal_False; First=sal_True;
+ WordEndCnt=0;
+
+ do { // mal schauen, wieviele Worte so in die Zeile passen
+ if (Border) c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,DoTrenn,Line,cLine);
+ else c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
+ AbsEnd=(c==AbsatzEnd || c==TextEnd);
+ //if not AbsEnd then
+ {
+ if (First) {
+ Just=R->Attrib.Justify & 0x0F; // Absatzformat steht wenn, dann am Anfang
+ }
+ Border=R->ChrXP>UmbWdt;
+ WordEnd=(AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0);
+ Trenn=c=='-';
+ if (WordEnd && !Border0) {
+ WordEndCnt++;
+ (*WErec)=(*R0);
+ WEnChar=nChars-1;
+ }
+ if (Trenn && !Border) {
+ WordEndCnt++;
+ (*WErec)=(*R);
+ WEnChar=nChars;
+ }
+ }
+ (*R0)=(*R); c0=c;
+ Border0=Border;
+ First=sal_False;
+ AbsEnd=AbsEnd || (nChars>=MaxLineChars);
+ } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
+
+ if (Border) { // Trennen und Quetschen
+ (*WErec0)=(*WErec); WEnChar0=WEnChar;
+ AbsEnd=sal_False; c0=0;
+ (*R)=(*WErec); nChars=WEnChar;
+ (*TRrec)=(*R); TRnChar=nChars;
+ Border0=sal_False; Border=sal_False;
+ do { // erst mal gucken wieviele Silben noch reinpassen
+ ct=ProcessChar(vOut,TBuf,*TRrec,Atr0,TRnChar,DoTrenn,Line,cLine);
+ c=ProcessChar(vOut,TBuf,*R,Atr0,nChars,NoTrenn,Line,cLine);
+ AbsEnd=(ct==AbsatzEnd) || (ct==TextEnd) || (nChars>=MaxLineChars);
+
+ Border=TRrec->ChrXP>UmbWdt;
+ WordEnd=AbsEnd || ((AbsEnd || (c==' ')) && (c0!=' ') && (c0!=0));
+ Trenn=ct=='-';
+ if (WordEnd && (!Border0 || (WordEndCnt==0))) {
+ WordEndCnt++;
+ (*WErec)=(*R0);
+ if (AbsEnd) WEnChar=nChars; else WEnChar=nChars-1;
+ (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
+ }
+ if (Trenn && (!Border || (WordEndCnt==0))) {
+ WordEndCnt++; // merken, dass man hier trennen kann
+ (*WErec)=(*TRrec);
+ WEnChar=TRnChar;
+ (*TRrec)=(*R); TRnChar=nChars; // zum weitersuchen
+ }
+ (*R0)=(*R); c0=c;
+ Border0=Border;
+ Border=R->ChrXP>UmbWdt;
+ } while (!(AbsEnd || (Border && ((WordEndCnt>0) || WordEnd || Trenn))));
+
+ while (WErec0->Index<WErec->Index) { // damit Line[] auch garantiert stimmt }
+ c=ProcessChar(vOut,TBuf,*WErec0,Atr0,WEnChar0,WEnChar-WEnChar0-1,Line,cLine);
+ }
+
+ (*R)=(*WErec); nChars=WEnChar;
+
+ if (UmbWdt>=R->ChrXP) {
+ BoxRest=UmbWdt-R->ChrXP;
+ } else { // Zusammenquetschen
+ BoxRest=R->ChrXP-UmbWdt; // um soviel muss gequetscht werden
+ for (i=2;i<=nChars;i++) { // 1. CharPosition bleibt !
+ Line[i]-=(i-1)*(BoxRest) /(nChars-1);
+ }
+ R->ChrXP=UmbWdt;
+ Line[nChars+1]=UmbWdt;
+ }
+ }
+
+ if (!AbsEnd) {
+ do { // Leerzeichen weglesen
+ (*WErec)=(*R);
+ c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False);
+ nChars++;
+ Line[nChars]=R->ChrXP;
+ cLine[nChars]=c;
+ } while (c==' ');
+ if (c!=' ' && c!=AbsatzEnd && c!=TextEnd) {
+ nChars--;
+ (*R)=(*WErec);
+ }
+ }
+
+ if (AbsEnd && nChars<MaxLineChars) { // Ausrichten, statt Blocksatz aber linksbuendig
+ if (Just==3) Just=0;
+ nChars++; Line[nChars]=R->ChrXP; // Damit AbsatzEnde auch weggelesen wird
+ Line[nChars+1]=R->ChrXP; // denn die Breite von CR oder #0 ist nun mal sehr klein
+ if (TBuf[R->Index-1]!=AbsatzEnd && TBuf[R->Index-1]!=TextEnd) {
+ c=GetTextChar(TBuf,R->Index,Atr0,R->Attrib,NoTrenn,sal_False); // Kleine Korrektur. Notig, wenn nur 1 Wort in
+ }
+ }
+
+ BoxRest=AdjWdt-R->ChrXP;
+ if (TextFit) Just=THJustLeft;
+
+ switch (Just) {
+ case THJustLeft: break; // Links
+ case THJustCenter: {
+ BoxRest=BoxRest /2; // Mitte
+ for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
+ } break;
+ case THJustRight: { // Rechts
+ for (i=1;i<=nChars;i++) Line[i]=Line[i]+BoxRest;
+ } break;
+ case THJustDrvOut:
+ case THJustBlock: { // Block und Austreibend
+ re=nChars;
+ if (Just==THJustDrvOut) re--;
+ while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
+ li=1;
+ while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
+ if (Just==THJustDrvOut) BoxRest=AdjWdt-Line[re+1];
+
+ j=0; // Anzahl der Spaces ermitteln
+ for (i=li;i<=re;i++) {
+ if (cLine[i]==' ') {
+ j++;
+ }
+ }
+
+ if (j==0) { // nur 1 Wort ? -> Strecken !
+ for (i=li+1;i<=re;i++) { // von links nach rechts
+ Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
+ }
+ } else {
+ k=0; h=0;
+ for (i=li;i<=re;i++) { // j Spaces aufbohren !
+ if (cLine[i]==' ') { // Space gefunden !
+ k++;
+ h=MulDiv(k,BoxRest,j);
+ }
+ Line[i]=Line[i]+h;
+ }
+ }
+ for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
+ Line[nChars+1]=AdjWdt;
+ } break;
+ case THJustLocked: { //Gesperrt
+ re=nChars-1;
+ while (re>=1 && (cLine[re]==' ' || cLine[re]==TextEnd || cLine[re]==AbsatzEnd)) re--;
+ li=1;
+ while (li<=re && (cLine[li]==' ' || cLine[li]==TextEnd || cLine[li]==AbsatzEnd)) li++;
+ BoxRest=AdjWdt-Line[re+1];
+ for (i=li+1;i<=re;i++) { // Strecken von links nach rechts
+ Line[i]=Line[i]+MulDiv(i-li,BoxRest,re-li+1-1);
+ }
+ for (i=re+1;i<=nChars;i++) Line[i]=Line[i]+BoxRest; // und den Rest anpassen
+ Line[nChars+1]=AdjWdt;
+ } break;
+ }
+ Index=R->Index;
+ AktAtr=R->Attrib;
+ delete R;
+ delete R0;
+ delete WErec;
+ delete WErec0;
+ delete TRrec;
+}
+
+
+
+// End of Absatz.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+// DrawText.Pas
+
+void DrawChar(OutputDevice& rOut, UCHAR c, ObjTextType T, PointType Pos, sal_uInt16 DrehWink,
+ sal_uInt16 FitXMul, sal_uInt16 FitXDiv, sal_uInt16 FitYMul, sal_uInt16 FitYDiv)
+{
+ SetTextContext(rOut,T,UpcasePossible(c),DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
+ if ((T.Schnitt & TextKaptBit)!=0 && UpcasePossible(c)) c=Upcase(c);
+ rtl::OUString s(reinterpret_cast<const sal_Char*>(&c), 1,
+ RTL_TEXTENCODING_IBM_437);
+ rOut.DrawText( Point( Pos.x, Pos.y ), s );
+}
+
+/*************************************************************************
+|*
+|* TextType::Draw()
+|*
+*************************************************************************/
+void TextType::Draw(OutputDevice& rOut)
+{
+ if ((Flags & TextOutlBit)!=0) return; // Sourcetext fuer Outliner !!
+
+ ObjTextType T1,T2;
+ sal_uInt16 Index1;
+ sal_uInt16 Index2;
+ UCHAR c = TextEnd;
+ sal_uInt16 l; // Anzahl der Zeichen in der Zeile
+ sal_uInt16 i;
+ short yPos0;
+ short xPos;
+ short yPos;
+ sal_uInt16 LF;
+ sal_uInt16 MaxGrad;
+ short xSize;
+ short xSAdj;
+ short ySize;
+ double sn,cs;
+ sal_uInt16 TopToBase;
+ sal_Bool Ende = 0;
+ sal_uInt16 lc;
+ sal_Bool LineFit; // FitSize.x=0? oder Flags -> jede Zeile stretchen
+ sal_Bool TextFit;
+ short* xLine;
+ UCHAR* cLine; // Buffer fuer FormatLine
+ sal_uInt16 FitXMul;
+ sal_uInt16 FitXDiv;
+ sal_uInt16 FitYMul;
+ sal_uInt16 FitYDiv;
+ sal_Bool Fehler;
+ UCHAR* Buf=Buffer; // Zeiger auf die Buchstaben
+
+ pSgfFonts->ReadList();
+ xLine=new short[ChrXPosArrSize];
+ cLine=new UCHAR[CharLineSize];
+
+ TextFit=(Flags & TextFitBits)!=0;
+ LineFit=sal_False;
+ LineFit=((Flags & TextFitZBit)!=0);
+ if (TextFit && FitSize.x==0) LineFit=sal_True;
+
+ if (DrehWink==0) {
+ sn=0.0;
+ cs=1.0;
+ } else {
+ sn=sin(double(DrehWink)*3.14159265359/18000);
+ cs=cos(double(DrehWink)*3.14159265359/18000);
+ }
+
+ T1=T; Index1=0; yPos=0; xPos=0;
+ if (TextFit) {
+ ySize=Pos2.y-Pos1.y;
+ xSize=32000 /2; // Umbruch
+ xSAdj=Pos2.x-Pos1.x; // zum Ausrichten bei Zentriert/Blocksatz
+ //if (xSize<=0) { xSize=32000 /2; LineFit=sal_True; }
+ FitXMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.x-Pos1.x)); FitXDiv=FitSize.x; if (FitXDiv==0) FitXDiv=1;
+ FitYMul=sal::static_int_cast< sal_uInt16 >(abs(Pos2.y-Pos1.y)); FitYDiv=FitSize.y; if (FitYDiv==0) FitYDiv=1;
+ } else {
+ xSize=Pos2.x-Pos1.x;
+ xSAdj=xSize;
+ ySize=Pos2.y-Pos1.y;
+ FitXMul=1; FitXDiv=1;
+ FitYMul=1; FitYDiv=1;
+ }
+ if (xSize<0) xSize=0;
+ if (xSAdj<0) xSAdj=0;
+
+ do {
+ T2=T1; Index2=Index1;
+ FormatLine(Buf,Index2,T,T2,xSize,xSAdj,xLine,l,sn,cs,cLine,LineFit);
+ Fehler=(Index2==Index1);
+ if (!Fehler) {
+ lc=GetLineFeed(Buf,Index1,T,T1,l,LF,MaxGrad);
+ if (TextFit) {
+ if (LineFit) FitXDiv=xLine[lc+1];
+ if (FitXDiv>0) {
+ long Temp;
+ for (i=1;i<=l+1;i++) {
+ Temp=long(xLine[i])*long(FitXMul) /long(FitXDiv);
+ xLine[i]=short(Temp);
+ }
+ LF=MulDiv(LF,FitYMul,FitYDiv);
+ MaxGrad=MulDiv(MaxGrad,FitYMul,FitYDiv);
+ } else {
+ FitXDiv=1; // 0 gibts nicht
+ }
+ }
+ yPos0=yPos;
+ TopToBase=GetTopToBaseLine(MaxGrad);
+ yPos=yPos+TopToBase;
+ Ende=(yPos0+short(MulDiv(MaxGrad,CharTopToBtm,100))>ySize) && !TextFit;
+ if (!Ende) {
+ T2=T1; Index2=Index1;
+ i=1;
+ while (i<=l) {
+ c=GetTextCharConv(Buf,Index2,T,T2,l-i,sal_False);
+ long xp1,yp1; // wegen Overflowgefahr
+ PointType Pos;
+ xp1=long(Pos1.x)+xPos+long(xLine[i]);
+ yp1=long(Pos1.y)+yPos;
+ if (xp1>32000) xp1=32000; if (xp1<-12000) xp1=-12000;
+ if (yp1>32000) yp1=32000; if (yp1<-12000) yp1=-12000;
+ Pos.x=short(xp1);
+ Pos.y=short(yp1);
+
+ if (DrehWink!=0) RotatePoint(Pos,Pos1.x,Pos1.y,sn,cs);
+ DrawChar(rOut,c,T2,Pos,DrehWink,FitXMul,FitXDiv,FitYMul,FitYDiv);
+ i++;
+ } // while i<=l
+ yPos=yPos0+LF;
+ T1=T2; Index1=Index2; // Fuer die naechste Zeile
+ } // if ObjMin.y+yPos<=Obj_Max.y
+ } // if !Fehler
+ } while (c!=TextEnd && !Ende && !Fehler);
+ delete[] cLine;
+ delete[] xLine;
+}
+
+// End of DrawText.Pas
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+// nicht mehr benoetigt, da der Pointer nun extra gefuehrt wird
+// (DEC Alpha hat naemlich 64Bit-Pointer!)
+//UCHAR* TextType::GetBufPtr()
+//{
+// sal_uLong Temp;
+// Temp=sal_uLong(BufLo)+0x00010000*sal_uLong(BufHi);
+// return (UCHAR*)Temp;
+//}
+//
+//void TextType::SetBufPtr(UCHAR* Ptr)
+//{
+// sal_uLong Temp=(sal_uLong)Ptr;
+// BufLo=sal_uInt16(Temp & 0x0000FFFF);
+// BufHi=sal_uInt16((Temp & 0xFFFF0000)>>16);
+//}
+
+sal_uInt32 ObjTextType::GetFont()
+{
+ return sal_uLong(FontLo)+0x00010000*sal_uLong(FontHi);
+}
+
+void ObjTextType::SetFont(sal_uInt32 FontID)
+{
+ FontLo=sal_uInt16(FontID & 0x0000FFFF);
+ FontHi=sal_uInt16((FontID & 0xFFFF0000)>>16);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// SGF.Ini lesen ////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+SgfFontOne::SgfFontOne()
+{
+ Next=NULL;
+ IFID=0;
+ Bold=sal_False;
+ Ital=sal_False;
+ Sans=sal_False;
+ Serf=sal_False;
+ Fixd=sal_False;
+ SVFamil=FAMILY_DONTKNOW;
+ SVChSet=RTL_TEXTENCODING_DONTKNOW;
+ SVWidth=40;
+}
+
+void SgfFontOne::ReadOne( const rtl::OString& rID, rtl::OString& Dsc )
+{
+ if ( Dsc.getLength() < 4 || ( Dsc[0] != '(' ) )
+ return;
+ sal_Int32 i=1; // Erster Buchstabe des IF-Fontnamen. Davor ist eine '('
+ while ( i < Dsc.getLength() && ( Dsc[i] !=')' ) )
+ i++;
+ Dsc = Dsc.copy(i+1); // IF-Fontname loeschen inkl. ()
+
+ if ( Dsc.getLength() < 2 || ( Dsc[Dsc.getLength() - 1] !=')' ) )
+ return;
+ i=Dsc.getLength()-2; // hier ist die ')' des SV-Fontnames
+ sal_Int32 j=0;
+ while ( i > 0 && ( Dsc[i] != '(' ) )
+ {
+ i--;
+ j++;
+ }
+ SVFName = rtl::OStringToOUString(Dsc.copy(i+1,j), RTL_TEXTENCODING_IBM_437); // SV-Fontname rausholen
+ Dsc = rtl::OStringBuffer(Dsc).remove(i,j).makeStringAndClear();
+
+ IFID = (sal_uInt32)rID.toInt32();
+ sal_Int32 nTokenCount = comphelper::string::getTokenCount(Dsc, ' ');
+ for (sal_Int32 nIdx = 0; nIdx < nTokenCount; ++nIdx)
+ {
+ rtl::OString s(Dsc.getToken(nIdx, ' '));
+ if (!s.isEmpty())
+ {
+ s = s.toAsciiUpperCase();
+ if (s.matchL(RTL_CONSTASCII_STRINGPARAM("BOLD"))) Bold=sal_True;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ITAL"))) Ital=sal_True;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SERF"))) Serf=sal_True;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SANS"))) Sans=sal_True;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("FIXD"))) Fixd=sal_True;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ROMAN"))) SVFamil=FAMILY_ROMAN;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SWISS"))) SVFamil=FAMILY_SWISS;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MODERN"))) SVFamil=FAMILY_MODERN;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SCRIPT"))) SVFamil=FAMILY_SCRIPT;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("DECORA"))) SVFamil=FAMILY_DECORATIVE;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("ANSI"))) SVChSet=RTL_TEXTENCODING_MS_1252;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("IBMPC"))) SVChSet=RTL_TEXTENCODING_IBM_850;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("MAC"))) SVChSet=RTL_TEXTENCODING_APPLE_ROMAN;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYMBOL"))) SVChSet=RTL_TEXTENCODING_SYMBOL;
+ else if (s.matchL(RTL_CONSTASCII_STRINGPARAM("SYSTEM"))) SVChSet = osl_getThreadTextEncoding();
+ else if (comphelper::string::isdigitAsciiString(s) ) SVWidth=sal::static_int_cast< sal_uInt16 >(s.toInt32());
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+SgfFontLst::SgfFontLst()
+{
+ pList=NULL;
+ Last=NULL;
+ LastID=0;
+ LastLn=NULL;
+ Tried=sal_False;
+}
+
+SgfFontLst::~SgfFontLst()
+{
+ RausList();
+}
+
+void SgfFontLst::RausList()
+{
+ SgfFontOne* P;
+ SgfFontOne* P1;
+ P=pList;
+ while (P!=NULL) {
+ P1=P->Next;
+ delete P;
+ P=P1;
+ }
+ pList=NULL;
+ Last=NULL;
+ Tried=sal_False;
+ LastID=0;
+ LastLn=NULL;
+}
+
+void SgfFontLst::AssignFN(const String& rFName)
+{ FNam=rFName; }
+
+void SgfFontLst::ReadList()
+{
+ if (!Tried)
+ {
+ Tried=sal_True;
+ LastID=0;
+ LastLn=NULL;
+ SgfFontOne* P,P1;
+ Config aCfg(FNam);
+ aCfg.SetGroup("SGV Fonts fuer StarView");
+ sal_uInt16 Anz=aCfg.GetKeyCount();
+ sal_uInt16 i;
+ rtl::OString FID;
+ rtl::OString Dsc;
+
+ for (i=0;i<Anz;i++)
+ {
+ FID = comphelper::string::remove(aCfg.GetKeyName(i), ' ');
+ Dsc = aCfg.ReadKey( i );
+ if (comphelper::string::isdigitAsciiString(FID))
+ {
+ P=new SgfFontOne; // neuer Eintrag
+ if (Last!=NULL) Last->Next=P; else pList=P; Last=P; // einklinken
+ P->ReadOne(FID,Dsc); // und Zeile interpretieren
+ }
+ }
+ }
+}
+
+SgfFontOne* SgfFontLst::GetFontDesc(sal_uInt32 ID)
+{
+ if (ID!=LastID) {
+ SgfFontOne* P;
+ P=pList;
+ while (P!=NULL && P->IFID!=ID) P=P->Next;
+ LastID=ID;
+ LastLn=P;
+ }
+ return LastLn;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/emfwr.cxx b/vcl/source/filter/wmf/emfwr.cxx
new file mode 100644
index 000000000000..c4caf024b47f
--- /dev/null
+++ b/vcl/source/filter/wmf/emfwr.cxx
@@ -0,0 +1,1412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "emfwr.hxx"
+#include <rtl/strbuf.hxx>
+#include <tools/helpers.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <vcl/lineinfo.hxx>
+
+// -----------
+// - Defines -
+// -----------
+
+#define WIN_EMR_HEADER 1
+#define WIN_EMR_POLYBEZIER 2
+#define WIN_EMR_POLYGON 3
+#define WIN_EMR_POLYLINE 4
+#define WIN_EMR_POLYBEZIERTO 5
+#define WIN_EMR_POLYLINETO 6
+#define WIN_EMR_POLYPOLYLINE 7
+#define WIN_EMR_POLYPOLYGON 8
+#define WIN_EMR_SETWINDOWEXTEX 9
+#define WIN_EMR_SETWINDOWORGEX 10
+#define WIN_EMR_SETVIEWPORTEXTEX 11
+#define WIN_EMR_SETVIEWPORTORGEX 12
+#define WIN_EMR_SETBRUSHORGEX 13
+#define WIN_EMR_EOF 14
+#define WIN_EMR_SETPIXELV 15
+#define WIN_EMR_SETMAPPERFLAGS 16
+#define WIN_EMR_SETMAPMODE 17
+#define WIN_EMR_SETBKMODE 18
+#define WIN_EMR_SETPOLYFILLMODE 19
+#define WIN_EMR_SETROP2 20
+#define WIN_EMR_SETSTRETCHBLTMODE 21
+#define WIN_EMR_SETTEXTALIGN 22
+#define WIN_EMR_SETCOLORADJUSTMENT 23
+#define WIN_EMR_SETTEXTCOLOR 24
+#define WIN_EMR_SETBKCOLOR 25
+#define WIN_EMR_OFFSETCLIPRGN 26
+#define WIN_EMR_MOVETOEX 27
+#define WIN_EMR_SETMETARGN 28
+#define WIN_EMR_EXCLUDECLIPRECT 29
+#define WIN_EMR_INTERSECTCLIPRECT 30
+#define WIN_EMR_SCALEVIEWPORTEXTEX 31
+#define WIN_EMR_SCALEWINDOWEXTEX 32
+#define WIN_EMR_SAVEDC 33
+#define WIN_EMR_RESTOREDC 34
+#define WIN_EMR_SETWORLDTRANSFORM 35
+#define WIN_EMR_MODIFYWORLDTRANSFORM 36
+#define WIN_EMR_SELECTOBJECT 37
+#define WIN_EMR_CREATEPEN 38
+#define WIN_EMR_CREATEBRUSHINDIRECT 39
+#define WIN_EMR_DELETEOBJECT 40
+#define WIN_EMR_ANGLEARC 41
+#define WIN_EMR_ELLIPSE 42
+#define WIN_EMR_RECTANGLE 43
+#define WIN_EMR_ROUNDRECT 44
+#define WIN_EMR_ARC 45
+#define WIN_EMR_CHORD 46
+#define WIN_EMR_PIE 47
+#define WIN_EMR_SELECTPALETTE 48
+#define WIN_EMR_CREATEPALETTE 49
+#define WIN_EMR_SETPALETTEENTRIES 50
+#define WIN_EMR_RESIZEPALETTE 51
+#define WIN_EMR_REALIZEPALETTE 52
+#define WIN_EMR_EXTFLOODFILL 53
+#define WIN_EMR_LINETO 54
+#define WIN_EMR_ARCTO 55
+#define WIN_EMR_POLYDRAW 56
+#define WIN_EMR_SETARCDIRECTION 57
+#define WIN_EMR_SETMITERLIMIT 58
+#define WIN_EMR_BEGINPATH 59
+#define WIN_EMR_ENDPATH 60
+#define WIN_EMR_CLOSEFIGURE 61
+#define WIN_EMR_FILLPATH 62
+#define WIN_EMR_STROKEANDFILLPATH 63
+#define WIN_EMR_STROKEPATH 64
+#define WIN_EMR_FLATTENPATH 65
+#define WIN_EMR_WIDENPATH 66
+#define WIN_EMR_SELECTCLIPPATH 67
+#define WIN_EMR_ABORTPATH 68
+
+#define WIN_EMR_GDICOMMENT 70
+#define WIN_EMR_FILLRGN 71
+#define WIN_EMR_FRAMERGN 72
+#define WIN_EMR_INVERTRGN 73
+#define WIN_EMR_PAINTRGN 74
+#define WIN_EMR_EXTSELECTCLIPRGN 75
+#define WIN_EMR_BITBLT 76
+#define WIN_EMR_STRETCHBLT 77
+#define WIN_EMR_MASKBLT 78
+#define WIN_EMR_PLGBLT 79
+#define WIN_EMR_SETDIBITSTODEVICE 80
+#define WIN_EMR_STRETCHDIBITS 81
+#define WIN_EMR_EXTCREATEFONTINDIRECTW 82
+#define WIN_EMR_EXTTEXTOUTA 83
+#define WIN_EMR_EXTTEXTOUTW 84
+#define WIN_EMR_POLYBEZIER16 85
+#define WIN_EMR_POLYGON16 86
+#define WIN_EMR_POLYLINE16 87
+#define WIN_EMR_POLYBEZIERTO16 88
+#define WIN_EMR_POLYLINETO16 89
+#define WIN_EMR_POLYPOLYLINE16 90
+#define WIN_EMR_POLYPOLYGON16 91
+#define WIN_EMR_POLYDRAW16 92
+#define WIN_EMR_CREATEMONOBRUSH 93
+#define WIN_EMR_CREATEDIBPATTERNBRUSHPT 94
+#define WIN_EMR_EXTCREATEPEN 95
+#define WIN_EMR_POLYTEXTOUTA 96
+#define WIN_EMR_POLYTEXTOUTW 97
+
+#define WIN_SRCCOPY 0x00CC0020L
+#define WIN_SRCPAINT 0x00EE0086L
+#define WIN_SRCAND 0x008800C6L
+#define WIN_SRCINVERT 0x00660046L
+
+#define HANDLE_INVALID 0xffffffff
+#define MAXHANDLES 65000
+
+#define LINE_SELECT 0x00000001
+#define FILL_SELECT 0x00000002
+#define TEXT_SELECT 0x00000004
+
+/* Text Alignment Options */
+#define TA_NOUPDATECP 0
+#define TA_UPDATECP 1
+
+#define TA_LEFT 0
+#define TA_RIGHT 2
+#define TA_CENTER 6
+
+#define TA_TOP 0
+#define TA_BOTTOM 8
+#define TA_BASELINE 24
+#define TA_RTLREADING 256
+#define TA_MASK (TA_BASELINE+TA_CENTER+TA_UPDATECP+TA_RTLREADING)
+
+#define MM_ANISOTROPIC 8
+
+// -------------
+// - EMFWriter -
+// -------------
+
+sal_Bool EMFWriter::WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pFilterConfigItem )
+{
+ const sal_uLong nHeaderPos = m_rStm.Tell();
+
+ mpHandlesUsed = new sal_Bool[ MAXHANDLES ];
+ memset( mpHandlesUsed, 0, MAXHANDLES * sizeof( sal_Bool ) );
+ mnHorTextAlign = mnHandleCount = mnLastPercent = mnRecordPos = mnRecordCount = 0;
+ mnLineHandle = mnFillHandle = mnTextHandle = HANDLE_INVALID;
+ mbRecordOpen = sal_False;
+
+ maVDev.EnableOutput( sal_False );
+ maVDev.SetMapMode( rMtf.GetPrefMapMode() );
+ mpFilterConfigItem = pFilterConfigItem;
+
+ // don't work with pixel as destination map mode -> higher resolution preferrable
+ maDestMapMode.SetMapUnit( MAP_100TH_MM );
+
+ const Size aMtfSizePix( maVDev.LogicToPixel( rMtf.GetPrefSize(), rMtf.GetPrefMapMode() ) );
+ const Size aMtfSizeLog( maVDev.LogicToLogic( rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MAP_100TH_MM ) );
+
+ // seek over header
+ // use [MS-EMF 2.2.11] HeaderExtension2 Object, otherwise resulting EMF cannot be converted with GetWinMetaFileBits()
+ m_rStm.SeekRel( 108 );
+
+ // write initial values
+
+ // set 100th mm map mode in EMF
+ ImplBeginRecord( WIN_EMR_SETMAPMODE );
+ m_rStm << (sal_Int32) MM_ANISOTROPIC;
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SETVIEWPORTEXTEX );
+ m_rStm << (sal_Int32) maVDev.ImplGetDPIX() << (sal_Int32) maVDev.ImplGetDPIY();
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SETWINDOWEXTEX );
+ m_rStm << (sal_Int32) 2540 << (sal_Int32) 2540;
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SETVIEWPORTORGEX );
+ m_rStm << (sal_Int32) 0 << (sal_Int32) 0;
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SETWINDOWORGEX );
+ m_rStm << (sal_Int32) 0 << (sal_Int32) 0;
+ ImplEndRecord();
+
+ ImplWriteRasterOp( ROP_OVERPAINT );
+
+ ImplBeginRecord( WIN_EMR_SETBKMODE );
+ m_rStm << (sal_uInt32) 1; // TRANSPARENT
+ ImplEndRecord();
+
+ // write emf data
+ ImplWrite( rMtf );
+
+ ImplBeginRecord( WIN_EMR_EOF );
+ m_rStm<< (sal_uInt32)0 // nPalEntries
+ << (sal_uInt32)0x10 // offPalEntries
+ << (sal_uInt32)0x14; // nSizeLast
+ ImplEndRecord();
+
+
+ // write header
+ const sal_uLong nEndPos = m_rStm.Tell(); m_rStm.Seek( nHeaderPos );
+
+ m_rStm << (sal_uInt32) 0x00000001 << (sal_uInt32) 108 //use [MS-EMF 2.2.11] HeaderExtension2 Object
+ << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizePix.Width() - 1 ) << (sal_Int32) ( aMtfSizePix.Height() - 1 )
+ << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) ( aMtfSizeLog.Width() - 1 ) << (sal_Int32) ( aMtfSizeLog.Height() - 1 )
+ << (sal_uInt32) 0x464d4520 << (sal_uInt32) 0x10000 << (sal_uInt32) ( nEndPos - nHeaderPos )
+ << (sal_uInt32) mnRecordCount << (sal_uInt16) ( mnHandleCount + 1 ) << (sal_uInt16) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0
+ << (sal_Int32) aMtfSizePix.Width() << (sal_Int32) aMtfSizePix.Height()
+ << (sal_Int32) ( aMtfSizeLog.Width() / 100 ) << (sal_Int32) ( aMtfSizeLog.Height() / 100 )
+ << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0
+ << (sal_Int32) ( aMtfSizeLog.Width() * 10 ) << (sal_Int32) ( aMtfSizeLog.Height() * 10 ); //use [MS-EMF 2.2.11] HeaderExtension2 Object
+
+ m_rStm.Seek( nEndPos );
+ delete[] mpHandlesUsed;
+
+ return( m_rStm.GetError() == ERRCODE_NONE );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_uLong EMFWriter::ImplAcquireHandle()
+{
+ sal_uLong nHandle = HANDLE_INVALID;
+
+ for( sal_uLong i = 0; i < MAXHANDLES && ( HANDLE_INVALID == nHandle ); i++ )
+ {
+ if( !mpHandlesUsed[ i ] )
+ {
+ mpHandlesUsed[ i ] = sal_True;
+
+ if( ( nHandle = i ) == mnHandleCount )
+ mnHandleCount++;
+ }
+ }
+
+ DBG_ASSERT( nHandle != HANDLE_INVALID, "No more handles available" );
+ return( nHandle != HANDLE_INVALID ? nHandle + 1 : HANDLE_INVALID );
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplReleaseHandle( sal_uLong nHandle )
+{
+ DBG_ASSERT( nHandle && ( nHandle < MAXHANDLES ), "Handle out of range" );
+ mpHandlesUsed[ nHandle - 1 ] = sal_False;
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplBeginRecord( sal_uInt32 nType )
+{
+ DBG_ASSERT( !mbRecordOpen, "Another record is already opened!" );
+
+ if( !mbRecordOpen )
+ {
+ mbRecordOpen = sal_True;
+ mnRecordPos = m_rStm.Tell();
+
+ m_rStm << nType;
+ m_rStm.SeekRel( 4 );
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplEndRecord()
+{
+ DBG_ASSERT( mbRecordOpen, "Record was not opened!" );
+
+ if( mbRecordOpen )
+ {
+ sal_Int32 nFillBytes, nActPos = m_rStm.Tell();
+ m_rStm.Seek( mnRecordPos + 4 );
+ nFillBytes = nActPos - mnRecordPos;
+ nFillBytes += 3; // each record has to be dword aligned
+ nFillBytes ^= 3;
+ nFillBytes &= 3;
+ m_rStm << (sal_uInt32)( ( nActPos - mnRecordPos ) + nFillBytes );
+ m_rStm.Seek( nActPos );
+ while( nFillBytes-- )
+ m_rStm << (sal_uInt8)0;
+ mnRecordCount++;
+ mbRecordOpen = sal_False;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool EMFWriter::ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType )
+{
+ if( rHandle != HANDLE_INVALID )
+ {
+ sal_uInt32 nStockObject = 0x80000000;
+
+ if( LINE_SELECT == nSelectType )
+ nStockObject |= 0x00000007;
+ else if( FILL_SELECT == nSelectType )
+ nStockObject |= 0x00000001;
+ else if( TEXT_SELECT == nSelectType )
+ nStockObject |= 0x0000000a;
+
+ // select stock object first
+ ImplBeginRecord( WIN_EMR_SELECTOBJECT );
+ m_rStm << nStockObject;
+ ImplEndRecord();
+
+ // destroy handle of created object
+ ImplBeginRecord( WIN_EMR_DELETEOBJECT );
+ m_rStm << rHandle;
+ ImplEndRecord();
+
+ // mark handle as free
+ ImplReleaseHandle( rHandle );
+ }
+
+ rHandle = ImplAcquireHandle();
+
+ return( HANDLE_INVALID != rHandle );
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplCheckLineAttr()
+{
+ if( mbLineChanged && ImplPrepareHandleSelect( mnLineHandle, LINE_SELECT ) )
+ {
+ sal_uInt32 nStyle = maVDev.IsLineColor() ? 0 : 5;
+ sal_uInt32 nWidth = 0, nHeight = 0;
+
+ ImplBeginRecord( WIN_EMR_CREATEPEN );
+ m_rStm << mnLineHandle << nStyle << nWidth << nHeight;
+ ImplWriteColor( maVDev.GetLineColor() );
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SELECTOBJECT );
+ m_rStm << mnLineHandle;
+ ImplEndRecord();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplCheckFillAttr()
+{
+ if( mbFillChanged && ImplPrepareHandleSelect( mnFillHandle, FILL_SELECT ) )
+ {
+ sal_uInt32 nStyle = maVDev.IsFillColor() ? 0 : 1;
+ sal_uInt32 nPatternStyle = 0;
+
+ ImplBeginRecord( WIN_EMR_CREATEBRUSHINDIRECT );
+ m_rStm << mnFillHandle << nStyle;
+ ImplWriteColor( maVDev.GetFillColor() );
+ m_rStm << nPatternStyle;
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SELECTOBJECT );
+ m_rStm << mnFillHandle;
+ ImplEndRecord();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplCheckTextAttr()
+{
+ if( mbTextChanged && ImplPrepareHandleSelect( mnTextHandle, TEXT_SELECT ) )
+ {
+ const Font& rFont = maVDev.GetFont();
+ String aFontName( rFont.GetName() );
+ sal_Int32 nWeight;
+ sal_uInt16 i;
+ sal_uInt8 nPitchAndFamily;
+
+ ImplBeginRecord( WIN_EMR_EXTCREATEFONTINDIRECTW );
+ m_rStm << mnTextHandle;
+ ImplWriteExtent( -rFont.GetSize().Height() );
+ ImplWriteExtent( rFont.GetSize().Width() );
+ m_rStm << (sal_Int32) rFont.GetOrientation() << (sal_Int32) rFont.GetOrientation();
+
+ switch( rFont.GetWeight() )
+ {
+ case WEIGHT_THIN: nWeight = 100; break;
+ case WEIGHT_ULTRALIGHT: nWeight = 200; break;
+ case WEIGHT_LIGHT: nWeight = 300; break;
+ case WEIGHT_SEMILIGHT: nWeight = 300; break;
+ case WEIGHT_NORMAL: nWeight = 400; break;
+ case WEIGHT_MEDIUM: nWeight = 500; break;
+ case WEIGHT_SEMIBOLD: nWeight = 600; break;
+ case WEIGHT_BOLD: nWeight = 700; break;
+ case WEIGHT_ULTRABOLD: nWeight = 800; break;
+ case WEIGHT_BLACK: nWeight = 900; break;
+ default: nWeight = 0; break;
+ }
+
+ m_rStm << nWeight;
+ m_rStm << (sal_uInt8) ( ( ITALIC_NONE == rFont.GetItalic() ) ? 0 : 1 );
+ m_rStm << (sal_uInt8) ( ( UNDERLINE_NONE == rFont.GetUnderline() ) ? 0 : 1 );
+ m_rStm << (sal_uInt8) ( ( STRIKEOUT_NONE == rFont.GetStrikeout() ) ? 0 : 1 );
+ m_rStm << (sal_uInt8) ( ( RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet() ) ? 2 : 0 );
+ m_rStm << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0;
+
+ switch( rFont.GetPitch() )
+ {
+ case PITCH_FIXED: nPitchAndFamily = 0x01; break;
+ case PITCH_VARIABLE: nPitchAndFamily = 0x02; break;
+ default: nPitchAndFamily = 0x00; break;
+ }
+
+ switch( rFont.GetFamily() )
+ {
+ case FAMILY_DECORATIVE: nPitchAndFamily |= 0x50; break;
+ case FAMILY_MODERN: nPitchAndFamily |= 0x30; break;
+ case FAMILY_ROMAN: nPitchAndFamily |= 0x10; break;
+ case FAMILY_SCRIPT: nPitchAndFamily |= 0x40; break;
+ case FAMILY_SWISS: nPitchAndFamily |= 0x20; break;
+ default: break;
+ }
+
+ m_rStm << nPitchAndFamily;
+
+ for( i = 0; i < 32; i++ )
+ m_rStm << (sal_Unicode) ( ( i < aFontName.Len() ) ? aFontName.GetChar( i ) : 0 );
+
+ // dummy elfFullName
+ for( i = 0; i < 64; i++ )
+ m_rStm << (sal_Unicode) 0;
+
+ // dummy elfStyle
+ for( i = 0; i < 32; i++ )
+ m_rStm << (sal_Unicode) 0;
+
+ // dummy elfVersion, elfStyleSize, elfMatch, elfReserved
+ m_rStm << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 << (sal_uInt32) 0 ;
+
+ // dummy elfVendorId
+ m_rStm << (sal_uInt32) 0;
+
+ // dummy elfCulture
+ m_rStm << (sal_uInt32) 0;
+
+ // dummy elfPanose
+ m_rStm << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0 << (sal_uInt8) 0;
+
+ // fill record to get a record size divideable by 4
+ m_rStm << (sal_uInt16) 0;
+
+ ImplEndRecord();
+
+ // TextAlign
+ sal_uInt32 nTextAlign;
+
+ switch( rFont.GetAlign() )
+ {
+ case ALIGN_TOP: nTextAlign = TA_TOP; break;
+ case ALIGN_BOTTOM: nTextAlign = TA_BOTTOM; break;
+ default: nTextAlign = TA_BASELINE; break;
+ }
+ nTextAlign |= mnHorTextAlign;
+
+ ImplBeginRecord( WIN_EMR_SETTEXTALIGN );
+ m_rStm << nTextAlign;
+ ImplEndRecord();
+
+ // Text color
+ ImplBeginRecord( WIN_EMR_SETTEXTCOLOR );
+ ImplWriteColor( maVDev.GetTextColor() );
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SELECTOBJECT );
+ m_rStm << mnTextHandle;
+ ImplEndRecord();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteColor( const Color& rColor )
+{
+ sal_uInt32 nCol = rColor.GetRed();
+
+ nCol |= ( (sal_uInt32) rColor.GetGreen() ) << 8;
+ nCol |= ( (sal_uInt32) rColor.GetBlue() ) << 16;
+
+ m_rStm << nCol;
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteRasterOp( RasterOp eRop )
+{
+ sal_uInt32 nROP2;
+
+ switch( eRop )
+ {
+ case ROP_INVERT: nROP2 = 6; break;
+ case ROP_XOR: nROP2 = 7; break;
+ default: nROP2 = 13;break;
+ }
+
+ ImplBeginRecord( WIN_EMR_SETROP2 );
+ m_rStm << nROP2;
+ ImplEndRecord();
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteExtent( long nExtent )
+{
+ nExtent = maVDev.LogicToLogic( Size( nExtent, 0 ), maVDev.GetMapMode(), maDestMapMode ).Width();
+ m_rStm << (sal_Int32) nExtent;
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWritePoint( const Point& rPoint )
+{
+ const Point aPoint( maVDev.LogicToLogic( rPoint, maVDev.GetMapMode(), maDestMapMode ));
+ m_rStm << (sal_Int32) aPoint.X() << (sal_Int32) aPoint.Y();
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteSize( const Size& rSize)
+{
+ const Size aSize( maVDev.LogicToLogic( rSize, maVDev.GetMapMode(), maDestMapMode ));
+ m_rStm << (sal_Int32) aSize.Width() << (sal_Int32) aSize.Height();
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteRect( const Rectangle& rRect )
+{
+ const Rectangle aRect( maVDev.LogicToLogic ( rRect, maVDev.GetMapMode(), maDestMapMode ));
+ m_rStm
+ << static_cast<sal_Int32>(aRect.Left())
+ << static_cast<sal_Int32>(aRect.Top())
+ << static_cast<sal_Int32>(aRect.Right())
+ << static_cast<sal_Int32>(aRect.Bottom());
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose )
+{
+ if( rPoly.GetSize() )
+ {
+ if( rPoly.HasFlags() )
+ ImplWritePath( rPoly, bClose );
+ else
+ {
+ if( bClose )
+ ImplCheckFillAttr();
+
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( bClose ? WIN_EMR_POLYGON : WIN_EMR_POLYLINE );
+ ImplWriteRect( rPoly.GetBoundRect() );
+ m_rStm << (sal_uInt32) rPoly.GetSize();
+
+ for( sal_uInt16 i = 0; i < rPoly.GetSize(); i++ )
+ ImplWritePoint( rPoly[ i ] );
+
+ ImplEndRecord();
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly )
+{
+ sal_uInt16 n, i, nPolyCount = rPolyPoly.Count();
+
+ if( nPolyCount )
+ {
+ if( 1 == nPolyCount )
+ ImplWritePolygonRecord( rPolyPoly[ 0 ], sal_True );
+ else
+ {
+ sal_Bool bHasFlags = sal_False;
+ sal_uInt32 nTotalPoints = 0;
+
+ for( i = 0; i < nPolyCount; i++ )
+ {
+ nTotalPoints += rPolyPoly[ i ].GetSize();
+ if ( rPolyPoly[ i ].HasFlags() )
+ bHasFlags = sal_True;
+ }
+ if( nTotalPoints )
+ {
+ if ( bHasFlags )
+ ImplWritePath( rPolyPoly, sal_True );
+ else
+ {
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_POLYPOLYGON );
+ ImplWriteRect( rPolyPoly.GetBoundRect() );
+ m_rStm << (sal_uInt32)nPolyCount << nTotalPoints;
+
+ for( i = 0; i < nPolyCount; i++ )
+ m_rStm << (sal_uInt32)rPolyPoly[ i ].GetSize();
+
+ for( i = 0; i < nPolyCount; i++ )
+ {
+ const Polygon& rPoly = rPolyPoly[ i ];
+
+ for( n = 0; n < rPoly.GetSize(); n++ )
+ ImplWritePoint( rPoly[ n ] );
+ }
+ ImplEndRecord();
+ }
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClosed )
+{
+ if ( bClosed )
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_BEGINPATH );
+ ImplEndRecord();
+
+ sal_uInt16 i, n, o, nPolyCount = rPolyPoly.Count();
+ for ( i = 0; i < nPolyCount; i++ )
+ {
+ n = 0;
+ const Polygon& rPoly = rPolyPoly[ i ];
+ while ( n < rPoly.GetSize() )
+ {
+ if( n == 0 )
+ {
+ ImplBeginRecord( WIN_EMR_MOVETOEX );
+ ImplWritePoint( rPoly[ 0 ] );
+ ImplEndRecord();
+ n++;
+ continue;
+ }
+
+ sal_uInt16 nBezPoints = 0;
+
+ while ( ( ( nBezPoints + n + 2 ) < rPoly.GetSize() ) && ( rPoly.GetFlags( nBezPoints + n ) == POLY_CONTROL ) )
+ nBezPoints += 3;
+
+ if ( nBezPoints )
+ {
+ ImplBeginRecord( WIN_EMR_POLYBEZIERTO );
+ Polygon aNewPoly( nBezPoints + 1 );
+ aNewPoly[ 0 ] = rPoly[ n - 1 ];
+ for ( o = 0; o < nBezPoints; o++ )
+ aNewPoly[ o + 1 ] = rPoly[ n + o ];
+ ImplWriteRect( aNewPoly.GetBoundRect() );
+ m_rStm << (sal_uInt32)nBezPoints;
+ for( o = 1; o < aNewPoly.GetSize(); o++ )
+ ImplWritePoint( aNewPoly[ o ] );
+ ImplEndRecord();
+ n = n + nBezPoints;
+ }
+ else
+ {
+ sal_uInt16 nPoints = 1;
+ while( ( nPoints + n ) < rPoly.GetSize() && ( rPoly.GetFlags( nPoints + n ) != POLY_CONTROL ) )
+ nPoints++;
+
+ if ( nPoints > 1 )
+ {
+ ImplBeginRecord( WIN_EMR_POLYLINETO );
+ Polygon aNewPoly( nPoints + 1 );
+ aNewPoly[ 0 ] = rPoly[ n - 1];
+ for ( o = 1; o <= nPoints; o++ )
+ aNewPoly[ o ] = rPoly[ n - 1 + o ];
+ ImplWriteRect( aNewPoly.GetBoundRect() );
+ m_rStm << (sal_uInt32)( nPoints );
+ for( o = 1; o < aNewPoly.GetSize(); o++ )
+ ImplWritePoint( aNewPoly[ o ] );
+ ImplEndRecord();
+ }
+ else
+ {
+ ImplBeginRecord( WIN_EMR_LINETO );
+ ImplWritePoint( rPoly[ n ] );
+ ImplEndRecord();
+ }
+ n = n + nPoints;
+ }
+ if ( bClosed && ( n == rPoly.GetSize() ) )
+ {
+ ImplBeginRecord( WIN_EMR_CLOSEFIGURE );
+ ImplEndRecord();
+ }
+ }
+ }
+ ImplBeginRecord( WIN_EMR_ENDPATH );
+ ImplEndRecord();
+ ImplBeginRecord( bClosed ? WIN_EMR_FILLPATH : WIN_EMR_STROKEPATH );
+ ImplWriteRect( rPolyPoly.GetBoundRect() );
+ ImplEndRecord();
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt,
+ const Size& rSz, sal_uInt32 nROP )
+{
+ if( !!rBmp )
+ {
+ SvMemoryStream aMemStm( 65535, 65535 );
+ const Size aBmpSizePixel( rBmp.GetSizePixel() );
+
+ ImplBeginRecord( WIN_EMR_STRETCHDIBITS );
+ ImplWriteRect( Rectangle( rPt, rSz ) );
+ ImplWritePoint( rPt );
+ m_rStm << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) aBmpSizePixel.Width() << (sal_Int32) aBmpSizePixel.Height();
+
+ // write offset positions and sizes later
+ const sal_uLong nOffPos = m_rStm.Tell();
+ m_rStm.SeekRel( 16 );
+
+ m_rStm << (sal_uInt32) 0 << sal_Int32( ( ROP_XOR == maVDev.GetRasterOp() && WIN_SRCCOPY == nROP ) ? WIN_SRCINVERT : nROP );
+ ImplWriteSize( rSz );
+
+ rBmp.Write( aMemStm, sal_True, sal_False );
+
+ sal_uInt32 nDIBSize = aMemStm.Tell(), nHeaderSize, nCompression, nColsUsed, nPalCount, nImageSize;
+ sal_uInt16 nBitCount;
+
+ // get DIB parameters
+ aMemStm.Seek( 0 );
+ aMemStm >> nHeaderSize;
+ aMemStm.SeekRel( 10 );
+ aMemStm >> nBitCount >> nCompression >> nImageSize;
+ aMemStm.SeekRel( 8 );
+ aMemStm >> nColsUsed;
+
+ nPalCount = ( nBitCount <= 8 ) ? ( nColsUsed ? nColsUsed : ( 1 << (sal_uInt32) nBitCount ) ) :
+ ( ( 3 == nCompression ) ? 12 : 0 );
+
+ m_rStm.Write( aMemStm.GetData(), nDIBSize );
+
+ const sal_uLong nEndPos = m_rStm.Tell();
+ m_rStm.Seek( nOffPos );
+ m_rStm << (sal_uInt32) 80 << (sal_uInt32)( nHeaderSize + ( nPalCount << 2 ) );
+ m_rStm << (sal_uInt32)( 80 + ( nHeaderSize + ( nPalCount << 2 ) ) ) << nImageSize;
+ m_rStm.Seek( nEndPos );
+
+ ImplEndRecord();
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth )
+{
+ xub_StrLen nLen = rText.Len(), i;
+
+ if( nLen )
+ {
+ sal_uInt32 nNormWidth;
+ sal_Int32* pOwnArray;
+ sal_Int32* pDX;
+
+ // get text sizes
+ if( pDXArray )
+ {
+ pOwnArray = NULL;
+ nNormWidth = maVDev.GetTextWidth( rText );
+ pDX = (sal_Int32*) pDXArray;
+ }
+ else
+ {
+ pOwnArray = new sal_Int32[ nLen ];
+ nNormWidth = maVDev.GetTextArray( rText, pOwnArray );
+ pDX = pOwnArray;
+ }
+
+ if( nLen > 1 )
+ {
+ nNormWidth = pDX[ nLen - 2 ] + maVDev.GetTextWidth( rtl::OUString(rText.GetChar( nLen - 1 )) );
+
+ if( nWidth && nNormWidth && ( nWidth != nNormWidth ) )
+ {
+ const double fFactor = (double) nWidth / nNormWidth;
+
+ for( i = 0; i < ( nLen - 1 ); i++ )
+ pDX[ i ] = FRound( pDX[ i ] * fFactor );
+ }
+ }
+
+ // write text record
+ ImplBeginRecord( WIN_EMR_EXTTEXTOUTW );
+
+ ImplWriteRect( Rectangle( rPos, Size( nNormWidth, maVDev.GetTextHeight() ) ) );
+ m_rStm << (sal_uInt32)1;
+ m_rStm << (sal_Int32) 0 << (sal_Int32) 0;
+ ImplWritePoint( rPos );
+ m_rStm << (sal_uInt32) nLen << (sal_uInt32) 76 << (sal_uInt32) 2;
+ m_rStm << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int32) 0;
+ m_rStm << (sal_uInt32) ( 76 + ( nLen << 1 ) + ( (nLen & 1 ) ? 2 : 0 ) );
+
+ // write text
+ for( i = 0; i < nLen; i++ )
+ m_rStm << (sal_Unicode)rText.GetChar( i );
+
+ // padding word
+ if( nLen & 1 )
+ m_rStm << (sal_uInt16) 0;
+
+ // write DX array
+ ImplWriteExtent( pDX[ 0 ] );
+
+ if( nLen > 1 )
+ {
+ for( i = 1; i < ( nLen - 1 ); i++ )
+ ImplWriteExtent( pDX[ i ] - pDX[ i - 1 ] );
+
+ ImplWriteExtent( pDX[ nLen - 2 ] / ( nLen - 1 ) );
+ }
+
+ ImplEndRecord();
+ delete[] pOwnArray;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
+{
+ if(rLinePolygon.count())
+ {
+ basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+
+ rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
+
+ if(aLinePolyPolygon.count())
+ {
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ ImplWritePolygonRecord( Polygon(aCandidate), sal_False );
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(maVDev.GetLineColor());
+ const Color aOldFillColor(maVDev.GetFillColor());
+
+ maVDev.SetLineColor();
+ maVDev.SetFillColor(aOldLineColor);
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ ImplWritePolyPolygonRecord(PolyPolygon(Polygon(aPolygon)));
+ }
+
+ maVDev.SetLineColor(aOldLineColor);
+ maVDev.SetFillColor(aOldFillColor);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+void EMFWriter::ImplWrite( const GDIMetaFile& rMtf )
+{
+ for( size_t j = 0, nActionCount = rMtf.GetActionSize(); j < nActionCount; j++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( j );
+ const sal_uInt16 nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ const MetaPixelAction* pA = (const MetaPixelAction*) pAction;
+
+ ImplCheckLineAttr();
+ ImplBeginRecord( WIN_EMR_SETPIXELV );
+ ImplWritePoint( pA->GetPoint() );
+ ImplWriteColor( pA->GetColor() );
+ ImplEndRecord();
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ if( maVDev.IsLineColor() )
+ {
+ const MetaPointAction* pA = (const MetaPointAction*) pAction;
+
+ ImplCheckLineAttr();
+ ImplBeginRecord( WIN_EMR_SETPIXELV );
+ ImplWritePoint( pA->GetPoint() );
+ ImplWriteColor( maVDev.GetLineColor() );
+ ImplEndRecord();
+ }
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ if( maVDev.IsLineColor() )
+ {
+ const MetaLineAction* pA = (const MetaLineAction*) pAction;
+
+ if(pA->GetLineInfo().IsDefault())
+ {
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_MOVETOEX );
+ ImplWritePoint( pA->GetStartPoint() );
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_LINETO );
+ ImplWritePoint( pA->GetEndPoint() );
+ ImplEndRecord();
+
+ ImplBeginRecord( WIN_EMR_SETPIXELV );
+ ImplWritePoint( pA->GetEndPoint() );
+ ImplWriteColor( maVDev.GetLineColor() );
+ ImplEndRecord();
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
+ aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
+ Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
+ }
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ if( maVDev.IsLineColor() || maVDev.IsFillColor() )
+ {
+ const MetaRectAction* pA = (const MetaRectAction*) pAction;
+
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_RECTANGLE );
+ ImplWriteRect( pA->GetRect() );
+ ImplEndRecord();
+ }
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ if( maVDev.IsLineColor() || maVDev.IsFillColor() )
+ {
+ const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pAction;
+
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_ROUNDRECT );
+ ImplWriteRect( pA->GetRect() );
+ ImplWriteSize( Size( pA->GetHorzRound(), pA->GetVertRound() ) );
+ ImplEndRecord();
+ }
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ if( maVDev.IsLineColor() || maVDev.IsFillColor() )
+ {
+ const MetaEllipseAction* pA = (const MetaEllipseAction*) pAction;
+
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+
+ ImplBeginRecord( WIN_EMR_ELLIPSE );
+ ImplWriteRect( pA->GetRect() );
+ ImplEndRecord();
+ }
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ case( META_PIE_ACTION ):
+ case( META_CHORD_ACTION ):
+ case( META_POLYGON_ACTION ):
+ {
+ if( maVDev.IsLineColor() || maVDev.IsFillColor() )
+ {
+ 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;
+ }
+
+ ImplWritePolygonRecord( aPoly, nType != META_ARC_ACTION );
+ }
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ if( maVDev.IsLineColor() )
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pAction;
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ if(pA->GetLineInfo().IsDefault())
+ {
+ ImplWritePolygonRecord( rPoly, sal_False );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ Impl_handleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
+ }
+ }
+ }
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ if( maVDev.IsLineColor() || maVDev.IsFillColor() )
+ ImplWritePolyPolygonRecord( ( (const MetaPolyPolygonAction*) pAction )->GetPolyPolygon() );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
+ GDIMetaFile aTmpMtf;
+
+ maVDev.AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
+ ImplWrite( aTmpMtf );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ const MetaHatchAction* pA = (const MetaHatchAction*) pAction;
+ GDIMetaFile aTmpMtf;
+
+ maVDev.AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
+ ImplWrite( aTmpMtf );
+ }
+ break;
+
+ case META_TRANSPARENT_ACTION:
+ {
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+ ImplWritePolyPolygonRecord( ( (MetaTransparentAction*) pAction )->GetPolyPolygon() );
+ }
+ 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 );
+
+ ImplCheckFillAttr();
+ ImplCheckLineAttr();
+ ImplCheckTextAttr();
+ ImplWrite( aTmpMtf );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ const MetaEPSAction* pA = (const MetaEPSAction*) pAction;
+ const GDIMetaFile aSubstitute( pA->GetSubstitute() );
+
+ for( size_t i = 0, nCount = aSubstitute.GetActionSize(); i < nCount; i++ )
+ {
+ const MetaAction* pSubstAct = aSubstitute.GetAction( i );
+ if( pSubstAct->GetType() == META_BMPSCALE_ACTION )
+ {
+ maVDev.Push( PUSH_ALL );
+ ImplBeginRecord( WIN_EMR_SAVEDC );
+ ImplEndRecord();
+
+ MapMode aMapMode( aSubstitute.GetPrefMapMode() );
+ Size aOutSize( maVDev.LogicToLogic( pA->GetSize(), maVDev.GetMapMode(), aMapMode ) );
+ aMapMode.SetScaleX( Fraction( aOutSize.Width(), aSubstitute.GetPrefSize().Width() ) );
+ aMapMode.SetScaleY( Fraction( aOutSize.Height(), aSubstitute.GetPrefSize().Height() ) );
+ aMapMode.SetOrigin( maVDev.LogicToLogic( pA->GetPoint(), maVDev.GetMapMode(), aMapMode ) );
+ maVDev.SetMapMode( aMapMode );
+ ImplWrite( aSubstitute );
+
+ maVDev.Pop();
+ ImplBeginRecord( WIN_EMR_RESTOREDC );
+ m_rStm << (sal_Int32) -1;
+ ImplEndRecord();
+ break;
+ }
+ }
+ }
+ break;
+
+ case META_BMP_ACTION:
+ {
+ const MetaBmpAction* pA = (const MetaBmpAction *) pAction;
+ ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), maVDev.PixelToLogic( pA->GetBitmap().GetSizePixel() ), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_BMPSCALE_ACTION:
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pAction;
+ ImplWriteBmpRecord( pA->GetBitmap(), pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_BMPSCALEPART_ACTION:
+ {
+ const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pAction;
+ Bitmap aTmp( pA->GetBitmap() );
+
+ if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
+ ImplWriteBmpRecord( aTmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_BMPEX_ACTION:
+ {
+ const MetaBmpExAction* pA = (const MetaBmpExAction *) pAction;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ ImplWriteBmpRecord( aMsk, pA->GetPoint(), maVDev.PixelToLogic( aMsk.GetSizePixel() ), WIN_SRCPAINT );
+ ImplWriteBmpRecord( aBmp, pA->GetPoint(), maVDev.PixelToLogic( aBmp.GetSizePixel() ), WIN_SRCAND );
+ }
+ else
+ ImplWriteBmpRecord( aBmp, pA->GetPoint(), aBmp.GetSizePixel(), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_BMPEXSCALE_ACTION:
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pAction;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ ImplWriteBmpRecord( aMsk, pA->GetPoint(), pA->GetSize(), WIN_SRCPAINT );
+ ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCAND );
+ }
+ else
+ ImplWriteBmpRecord( aBmp, pA->GetPoint(), pA->GetSize(), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_BMPEXSCALEPART_ACTION:
+ {
+ const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pAction;
+ BitmapEx aBmpEx( pA->GetBitmapEx() );
+ aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
+ Bitmap aBmp( aBmpEx.GetBitmap() );
+ Bitmap aMsk( aBmpEx.GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ ImplWriteBmpRecord( aMsk, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCPAINT );
+ ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCAND );
+ }
+ else
+ ImplWriteBmpRecord( aBmp, pA->GetDestPoint(), pA->GetDestSize(), WIN_SRCCOPY );
+ }
+ break;
+
+ case META_TEXT_ACTION:
+ {
+ const MetaTextAction* pA = (const MetaTextAction*) pAction;
+ const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+
+ ImplCheckTextAttr();
+ ImplWriteTextRecord( pA->GetPoint(), aText, NULL, 0 );
+ }
+ break;
+
+ case META_TEXTRECT_ACTION:
+ {
+ const MetaTextRectAction* pA = (const MetaTextRectAction*) pAction;
+ const String aText( pA->GetText() );
+
+ ImplCheckTextAttr();
+ ImplWriteTextRecord( pA->GetRect().TopLeft(), aText, NULL, 0 );
+ }
+ break;
+
+ case META_TEXTARRAY_ACTION:
+ {
+ const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pAction;
+ const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+
+ ImplCheckTextAttr();
+ ImplWriteTextRecord( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
+ }
+ break;
+
+ case META_STRETCHTEXT_ACTION:
+ {
+ const MetaStretchTextAction* pA = (const MetaStretchTextAction*) pAction;
+ const String aText( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+
+ ImplCheckTextAttr();
+ ImplWriteTextRecord( pA->GetPoint(), aText, NULL, pA->GetWidth() );
+ }
+ break;
+
+ case( META_LINECOLOR_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ mbLineChanged = sal_True;
+ }
+ break;
+
+ case( META_FILLCOLOR_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ mbFillChanged = sal_True;
+ }
+ break;
+
+ case( META_TEXTCOLOR_ACTION ):
+ case( META_TEXTLINECOLOR_ACTION ):
+ case( META_TEXTFILLCOLOR_ACTION ):
+ case( META_TEXTALIGN_ACTION ):
+ case( META_FONT_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ mbTextChanged = sal_True;
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+
+ ImplBeginRecord( WIN_EMR_INTERSECTCLIPRECT );
+ ImplWriteRect( ( (MetaISectRectClipRegionAction*) pAction )->GetRect() );
+ ImplEndRecord();
+ }
+ break;
+
+ case( META_CLIPREGION_ACTION ):
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ }
+ break;
+
+ case( META_REFPOINT_ACTION ):
+ case( META_MAPMODE_ACTION ):
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ break;
+
+ case( META_PUSH_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+
+ ImplBeginRecord( WIN_EMR_SAVEDC );
+ ImplEndRecord();
+ }
+ break;
+
+ case( META_POP_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+
+ ImplBeginRecord( WIN_EMR_RESTOREDC );
+ m_rStm << (sal_Int32) -1;
+ ImplEndRecord();
+
+ ImplWriteRasterOp( maVDev.GetRasterOp() );
+ mbLineChanged = mbFillChanged = mbTextChanged = sal_True;
+ }
+ break;
+
+ case( META_RASTEROP_ACTION ):
+ {
+ ( (MetaAction*) pAction )->Execute( &maVDev );
+ ImplWriteRasterOp( ( (MetaRasterOpAction*) pAction )->GetRasterOp() );
+ }
+ break;
+
+ case( META_LAYOUTMODE_ACTION ):
+ {
+ sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pAction )->GetLayoutMode();
+ mnHorTextAlign = 0;
+ if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
+ {
+ mnHorTextAlign = TA_RIGHT | TA_RTLREADING;
+ }
+ if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
+ mnHorTextAlign |= TA_RIGHT;
+ else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
+ mnHorTextAlign &= ~TA_RIGHT;
+ break;
+ }
+
+ case( META_MASK_ACTION ):
+ case( META_MASKSCALE_ACTION ):
+ case( META_MASKSCALEPART_ACTION ):
+ case( META_WALLPAPER_ACTION ):
+ case( META_TEXTLINE_ACTION ):
+ case( META_COMMENT_ACTION ):
+ case( META_GRADIENTEX_ACTION ):
+ {
+ // !!! >>> we don't want to support these actions
+ }
+ break;
+
+ default:
+ OSL_FAIL(rtl::OStringBuffer(RTL_CONSTASCII_STRINGPARAM(
+ "EMFWriter::ImplWriteActions: unsupported MetaAction #" )).
+ append(static_cast<sal_Int32>(nType)).getStr());
+ break;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/emfwr.hxx b/vcl/source/filter/wmf/emfwr.hxx
new file mode 100644
index 000000000000..f930c352ae33
--- /dev/null
+++ b/vcl/source/filter/wmf/emfwr.hxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _EMFWR_HXX
+#define _EMFWR_HXX
+
+#include <vcl/metaact.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <svtools/fltcall.hxx>
+
+// -------------
+// - EMFWriter -
+// -------------
+
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
+class EMFWriter
+{
+private:
+
+ VirtualDevice maVDev;
+ MapMode maDestMapMode;
+ FilterConfigItem* mpFilterConfigItem;
+ SvStream& m_rStm;
+ sal_Bool* mpHandlesUsed;
+ sal_uLong mnHandleCount;
+ sal_uLong mnLastPercent;
+ sal_uLong mnRecordCount;
+ sal_uLong mnRecordPos;
+ sal_Bool mbRecordOpen;
+ sal_Bool mbLineChanged;
+ sal_uInt32 mnLineHandle;
+ sal_Bool mbFillChanged;
+ sal_uInt32 mnFillHandle;
+ sal_Bool mbTextChanged;
+ sal_uInt32 mnTextHandle;
+ sal_uInt32 mnHorTextAlign;
+
+ void ImplBeginRecord( sal_uInt32 nType );
+ void ImplEndRecord();
+
+ sal_uLong ImplAcquireHandle();
+ void ImplReleaseHandle( sal_uLong nHandle );
+
+ sal_Bool ImplPrepareHandleSelect( sal_uInt32& rHandle, sal_uLong nSelectType );
+ void ImplCheckLineAttr();
+ void ImplCheckFillAttr();
+ void ImplCheckTextAttr();
+
+ void ImplWriteColor( const Color& rColor );
+ void ImplWriteRasterOp( RasterOp eRop );
+ void ImplWriteExtent( long nExtent );
+ void ImplWritePoint( const Point& rPoint );
+ void ImplWriteSize( const Size& rSize);
+ void ImplWriteRect( const Rectangle& rRect );
+ void ImplWritePath( const PolyPolygon& rPolyPoly, sal_Bool bClose );
+ void ImplWritePolygonRecord( const Polygon& rPoly, sal_Bool bClose );
+ void ImplWritePolyPolygonRecord( const PolyPolygon& rPolyPoly );
+ void ImplWriteBmpRecord( const Bitmap& rBmp, const Point& rPt, const Size& rSz, sal_uInt32 nROP );
+ void ImplWriteTextRecord( const Point& rPos, const String rText, const sal_Int32* pDXArray, sal_uInt32 nWidth );
+
+ void Impl_handleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
+ void ImplWrite( const GDIMetaFile& rMtf );
+
+public:
+
+ EMFWriter(SvStream &rStream) : m_rStm(rStream) {}
+
+ sal_Bool WriteEMF( const GDIMetaFile& rMtf, FilterConfigItem* pConfigItem = NULL );
+};
+
+#endif // _EMFWR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
new file mode 100644
index 000000000000..f8b98845be4e
--- /dev/null
+++ b/vcl/source/filter/wmf/enhwmf.cxx
@@ -0,0 +1,1418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "winmtf.hxx"
+#include <osl/endian.h>
+#include <boost/bind.hpp>
+
+using namespace std;
+//=========================== GDI-Array ===================================
+
+#define EMR_HEADER 1
+#define EMR_POLYBEZIER 2
+#define EMR_POLYGON 3
+#define EMR_POLYLINE 4
+#define EMR_POLYBEZIERTO 5
+#define EMR_POLYLINETO 6
+#define EMR_POLYPOLYLINE 7
+#define EMR_POLYPOLYGON 8
+#define EMR_SETWINDOWEXTEX 9
+#define EMR_SETWINDOWORGEX 10
+#define EMR_SETVIEWPORTEXTEX 11
+#define EMR_SETVIEWPORTORGEX 12
+#define EMR_SETBRUSHORGEX 13
+#define EMR_EOF 14
+#define EMR_SETPIXELV 15
+#define EMR_SETMAPPERFLAGS 16
+#define EMR_SETMAPMODE 17
+#define EMR_SETBKMODE 18
+#define EMR_SETPOLYFILLMODE 19
+#define EMR_SETROP2 20
+#define EMR_SETSTRETCHBLTMODE 21
+#define EMR_SETTEXTALIGN 22
+#define EMR_SETCOLORADJUSTMENT 23
+#define EMR_SETTEXTCOLOR 24
+#define EMR_SETBKCOLOR 25
+#define EMR_OFFSETCLIPRGN 26
+#define EMR_MOVETOEX 27
+#define EMR_SETMETARGN 28
+#define EMR_EXCLUDECLIPRECT 29
+#define EMR_INTERSECTCLIPRECT 30
+#define EMR_SCALEVIEWPORTEXTEX 31
+#define EMR_SCALEWINDOWEXTEX 32
+#define EMR_SAVEDC 33
+#define EMR_RESTOREDC 34
+#define EMR_SETWORLDTRANSFORM 35
+#define EMR_MODIFYWORLDTRANSFORM 36
+#define EMR_SELECTOBJECT 37
+#define EMR_CREATEPEN 38
+#define EMR_CREATEBRUSHINDIRECT 39
+#define EMR_DELETEOBJECT 40
+#define EMR_ANGLEARC 41
+#define EMR_ELLIPSE 42
+#define EMR_RECTANGLE 43
+#define EMR_ROUNDRECT 44
+#define EMR_ARC 45
+#define EMR_CHORD 46
+#define EMR_PIE 47
+#define EMR_SELECTPALETTE 48
+#define EMR_CREATEPALETTE 49
+#define EMR_SETPALETTEENTRIES 50
+#define EMR_RESIZEPALETTE 51
+#define EMR_REALIZEPALETTE 52
+#define EMR_EXTFLOODFILL 53
+#define EMR_LINETO 54
+#define EMR_ARCTO 55
+#define EMR_POLYDRAW 56
+#define EMR_SETARCDIRECTION 57
+#define EMR_SETMITERLIMIT 58
+#define EMR_BEGINPATH 59
+#define EMR_ENDPATH 60
+#define EMR_CLOSEFIGURE 61
+#define EMR_FILLPATH 62
+#define EMR_STROKEANDFILLPATH 63
+#define EMR_STROKEPATH 64
+#define EMR_FLATTENPATH 65
+#define EMR_WIDENPATH 66
+#define EMR_SELECTCLIPPATH 67
+#define EMR_ABORTPATH 68
+
+#define EMR_GDICOMMENT 70
+#define EMR_FILLRGN 71
+#define EMR_FRAMERGN 72
+#define EMR_INVERTRGN 73
+#define EMR_PAINTRGN 74
+#define EMR_EXTSELECTCLIPRGN 75
+#define EMR_BITBLT 76
+#define EMR_STRETCHBLT 77
+#define EMR_MASKBLT 78
+#define EMR_PLGBLT 79
+#define EMR_SETDIBITSTODEVICE 80
+#define EMR_STRETCHDIBITS 81
+#define EMR_EXTCREATEFONTINDIRECTW 82
+#define EMR_EXTTEXTOUTA 83
+#define EMR_EXTTEXTOUTW 84
+#define EMR_POLYBEZIER16 85
+#define EMR_POLYGON16 86
+#define EMR_POLYLINE16 87
+#define EMR_POLYBEZIERTO16 88
+#define EMR_POLYLINETO16 89
+#define EMR_POLYPOLYLINE16 90
+#define EMR_POLYPOLYGON16 91
+#define EMR_POLYDRAW16 92
+#define EMR_CREATEMONOBRUSH 93
+#define EMR_CREATEDIBPATTERNBRUSHPT 94
+#define EMR_EXTCREATEPEN 95
+#define EMR_POLYTEXTOUTA 96
+#define EMR_POLYTEXTOUTW 97
+
+// WINDOWS VERSION >= 0x400
+#define EMR_SETICMMODE 98
+#define EMR_CREATECOLORSPACE 99
+#define EMR_SETCOLORSPACE 100
+#define EMR_DELETECOLORSPACE 101
+#define EMR_GLSRECORD 102
+#define EMR_GLSBOUNDEDRECORD 103
+#define EMR_PIXELFORMAT 104
+
+// WINDOWS VERSION >= 0x500
+#define EMR_DRAWESCAPE 105
+#define EMR_EXTESCAPE 106
+#define EMR_STARTDOC 107
+#define EMR_SMALLTEXTOUT 108
+#define EMR_FORCEUFIMAPPING 109
+#define EMR_NAMEDESCAPE 110
+#define EMR_COLORCORRECTPALETTE 111
+#define EMR_SETICMPROFILEA 112
+#define EMR_SETICMPROFILEW 113
+#define EMR_ALPHABLEND 114
+#define EMR_ALPHADIBBLEND 115
+#define EMR_TRANSPARENTBLT 116
+#define EMR_TRANSPARENTDIB 117
+#define EMR_GRADIENTFILL 118
+#define EMR_SETLINKEDUFIS 119
+#define EMR_SETTEXTJUSTIFICATION 120
+
+#if OSL_DEBUG_LEVEL > 1
+#define EMFP_DEBUG(x) x
+#else
+#define EMFP_DEBUG(x)
+#endif
+
+//-----------------------------------------------------------------------------------
+
+#ifdef OSL_BIGENDIAN
+// currently unused
+static float GetSwapFloat( SvStream& rSt )
+{
+ float fTmp;
+ sal_Int8* pPtr = (sal_Int8*)&fTmp;
+ rSt >> pPtr[3] >> pPtr[2] >> pPtr[1] >> pPtr[0]; // Little Endian <-> Big Endian switch
+ return fTmp;
+}
+#endif
+
+SvStream& operator>>( SvStream& rIn, XForm& rXForm )
+{
+ if ( sizeof( float ) != 4 )
+ {
+ OSL_FAIL( "EnhWMFReader::sizeof( float ) != 4" );
+ rXForm = XForm();
+ }
+ else
+ {
+#ifdef OSL_BIGENDIAN
+ rXForm.eM11 = GetSwapFloat( rIn );
+ rXForm.eM12 = GetSwapFloat( rIn );
+ rXForm.eM21 = GetSwapFloat( rIn );
+ rXForm.eM22 = GetSwapFloat( rIn );
+ rXForm.eDx = GetSwapFloat( rIn );
+ rXForm.eDy = GetSwapFloat( rIn );
+#else
+ rIn >> rXForm.eM11 >> rXForm.eM12 >> rXForm.eM21 >> rXForm.eM22
+ >> rXForm.eDx >> rXForm.eDy;
+#endif
+ }
+ return rIn;
+}
+
+static sal_Bool ImplReadRegion( PolyPolygon& rPolyPoly, SvStream& rSt, sal_uInt32 nLen )
+{
+ sal_Bool bOk = sal_False;
+ if ( nLen )
+ {
+ sal_uInt32 nHdSize, nType, nCount, nRgnSize, i;
+ rSt >> nHdSize
+ >> nType
+ >> nCount
+ >> nRgnSize;
+
+ if ( nCount && ( nType == RDH_RECTANGLES ) &&
+ ( nLen >= ( ( nCount << 4 ) + ( nHdSize - 16 ) ) ) )
+ {
+ sal_Int32 nx1, ny1, nx2, ny2;
+
+ for ( i = 0; i < nCount; i++ )
+ {
+ rSt >> nx1 >> ny1 >> nx2 >> ny2;
+
+ Rectangle aRect( Point( nx1, ny1 ), Point( nx2, ny2 ) );
+ Polygon aPolygon( aRect );
+ PolyPolygon aPolyPolyOr1( aPolygon );
+ PolyPolygon aPolyPolyOr2( rPolyPoly );
+ rPolyPoly.GetUnion( aPolyPolyOr1, aPolyPolyOr2 );
+ rPolyPoly = aPolyPolyOr2;
+ }
+ bOk = sal_True;
+ }
+ }
+ return bOk;
+}
+
+EMFP_DEBUG(void dumpWords( SvStream& s, int i )
+{
+ sal_uInt32 pos = s.Tell();
+ sal_Int16 data;
+ for( ; i > 0; i -- ) {
+ s >> data;
+ EMFP_DEBUG(printf ("\t\t\tdata: %04hx\n", data));
+ }
+ s.Seek (pos);
+});
+
+void EnhWMFReader::ReadEMFPlusComment(sal_uInt32 length, sal_Bool& bHaveDC)
+{
+ if (!bEMFPlus) {
+ pOut->PassEMFPlusHeaderInfo();
+
+ // debug code - write the stream to debug file /tmp/emf-stream.emf
+ EMFP_DEBUG(int pos = pWMF->Tell();
+ pWMF->Seek(0);
+ SvFileStream file( rtl::OUString( "/tmp/emf-stream.emf" ), STREAM_WRITE | STREAM_TRUNC );
+
+ *pWMF >> file;
+ file.Flush();
+ file.Close();
+
+ pWMF->Seek( pos );)
+ }
+ bEMFPlus = true;
+
+ sal_Size pos = pWMF->Tell();
+ void *buffer = malloc( length );
+ pOut->PassEMFPlus( buffer, pWMF->Read( buffer, length ) );
+ free( buffer );
+ pWMF->Seek( pos );
+
+ bHaveDC = false;
+
+ OSL_ASSERT(length >= 4);
+ //reduce by 32bit length itself, skip in SeekRel if
+ //impossibly unavailble
+ sal_uInt32 nRemainder = length >= 4 ? length-4 : length;
+
+ const size_t nRequiredHeaderSize = 12;
+ while (nRemainder >= nRequiredHeaderSize)
+ {
+ sal_uInt16 type(0), flags(0);
+ sal_uInt32 size(0), dataSize(0);
+
+ *pWMF >> type >> flags >> size >> dataSize;
+ nRemainder -= nRequiredHeaderSize;
+
+ EMFP_DEBUG(printf ("\t\tEMF+ record type: %d\n", type));
+
+ // GetDC
+ if( type == 16388 ) {
+ bHaveDC = true;
+ EMFP_DEBUG(printf ("\t\tEMF+ lock DC (device context)\n"));
+ }
+
+ //Get the length of the remaining data of this record based
+ //on the alleged size
+ sal_uInt32 nRemainingRecordData = size >= nRequiredHeaderSize ?
+ size-nRequiredHeaderSize : 0;
+ //clip to available size
+ nRemainingRecordData = std::min(nRemainingRecordData, nRemainder);
+ pWMF->SeekRel(nRemainingRecordData);
+ nRemainder -= nRemainingRecordData;
+ }
+ pWMF->SeekRel(nRemainder);
+}
+
+/**
+ * Reads polygons from the stream.
+ * The <class T> parameter is for the type of the points (sal_uInt32 or sal_uInt16).
+ * The <class Drawer> parameter is a boost binding for the method that will draw the polygon.
+ * skipFirst: if the first point read is the 0th point or the 1st point in the array.
+ * */
+template <class T, class Drawer>
+void EnhWMFReader::ReadAndDrawPolygon(Drawer drawer, const sal_Bool skipFirst)
+{
+ sal_uInt32 nPoints(0), nStartIndex(0);
+ pWMF->SeekRel( 16 );
+ *pWMF >> nPoints;
+ if (skipFirst)
+ {
+ nPoints ++;
+ nStartIndex ++;
+ }
+
+ Polygon aPolygon = ReadPolygon<T>(nStartIndex, nPoints);
+ drawer(pOut, aPolygon, skipFirst, bRecordPath);
+}
+
+
+/**
+ * Reads polygons from the stream.
+ * The <class T> parameter is for the type of the points
+ * nStartIndex: which is the starting index in the polygon of the first point read
+ * nPoints: number of points
+ * pWMF: the stream containings the polygons
+ * */
+template <class T>
+Polygon EnhWMFReader::ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints)
+{
+ Polygon aPolygon(nPoints);
+ for (sal_uInt16 i = nStartIndex ; i < nPoints && pWMF->good(); i++ )
+ {
+ T nX, nY;
+ *pWMF >> nX >> nY;
+ if (!pWMF->good())
+ break;
+ aPolygon[ i ] = Point( nX, nY );
+ }
+
+ return aPolygon;
+}
+
+/**
+ * Reads a polyline from the WMF file and draws it
+ * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+template <class T>
+void EnhWMFReader::ReadAndDrawPolyLine()
+{
+ sal_uInt32 nPoints;
+ sal_Int32 i, nPoly(0), nGesPoints(0);
+ pWMF->SeekRel( 0x10 );
+ // Number of Polygons:
+ *pWMF >> nPoly >> nGesPoints;
+
+ // taking the amount of points of each polygon, retrieving the total number of points
+ if ( pWMF->good() &&
+ ( static_cast< sal_uInt32 >(nPoly) < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
+ ( static_cast< sal_uInt32 >( nPoly ) * sizeof(sal_uInt16) ) <= ( nEndPos - pWMF->Tell() )
+ )
+ {
+ sal_uInt16* pnPoints = new sal_uInt16[ nPoly ];
+ for ( i = 0; i < nPoly && pWMF->good(); i++ )
+ {
+ *pWMF >> nPoints;
+ pnPoints[ i ] = (sal_uInt16)nPoints;
+ }
+ // Get polygon points:
+ for ( i = 0; ( i < nPoly ) && pWMF->good(); i++ )
+ {
+ Polygon aPolygon = ReadPolygon<T>(0, pnPoints[i]);
+ pOut->DrawPolyLine( aPolygon, sal_False, bRecordPath );
+ }
+ delete[] pnPoints;
+ }
+}
+
+/**
+ * Reads a poly polygon from the WMF file and draws it.
+ * The <class T> parameter refers to the type of the points. (e.g. sal_uInt16 or sal_uInt32)
+ * */
+template <class T>
+void EnhWMFReader::ReadAndDrawPolyPolygon()
+{
+ sal_uInt32 i, nPoly, nGesPoints, nPoints;
+ pWMF->SeekRel( 0x10 );
+ // Number of polygons
+ *pWMF >> nPoly >> nGesPoints;
+ if ( pWMF->good() &&
+ ( nGesPoints < SAL_MAX_UINT32 / sizeof(Point) ) && //check against numeric overflowing
+ ( nPoly < SAL_MAX_UINT32 / sizeof(sal_uInt16) ) &&
+ ( ( nPoly * sizeof( sal_uInt16 ) ) <= ( nEndPos - pWMF->Tell() ) ))
+ {
+ //Get number of points in each polygon
+ sal_uInt16 * pnPoints = new sal_uInt16[ nPoly ];
+ for ( i = 0; i < nPoly && pWMF->good(); i++ )
+ {
+ *pWMF >> nPoints;
+ pnPoints[ i ] = (sal_uInt16)nPoints;
+ } //end for
+ if ( pWMF->good() && ( nGesPoints * (sizeof(T)+sizeof(T)) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ // Get polygon points
+ Point * pPtAry = new Point[ nGesPoints ];
+ for ( i = 0; i < nGesPoints && pWMF->good(); i++ )
+ {
+ T nX, nY;
+ *pWMF >> nX >> nY;
+ pPtAry[ i ] = Point( nX, nY );
+ } //end for
+ // Create PolyPolygon Actions
+ PolyPolygon aPolyPoly( (sal_uInt16)nPoly, pnPoints, pPtAry );
+ pOut->DrawPolyPolygon( aPolyPoly, bRecordPath );
+ delete[] pPtAry;
+ } //end if
+ delete[] pnPoints;
+ } //end if
+}
+
+sal_Bool EnhWMFReader::ReadEnhWMF()
+{
+ sal_uInt32 nStretchBltMode = 0;
+ sal_uInt32 nRecType(0), nRecSize(0), nNextPos(0),
+ nW(0), nH(0), nColor(0), nIndex(0),
+ nDat32(0), nNom1(0), nDen1(0), nNom2(0), nDen2(0);
+ sal_Int32 nX32(0), nY32(0), nx32(0), ny32(0);
+
+ sal_Bool bFlag(sal_False), bStatus = ReadHeader();
+ sal_Bool bHaveDC = false;
+
+ static sal_Bool bEnableEMFPlus = ( getenv( "EMF_PLUS_DISABLE" ) == NULL );
+
+ while( bStatus && nRecordCount-- && pWMF->good())
+ {
+ *pWMF >> nRecType >> nRecSize;
+
+ if ( !pWMF->good() || ( nRecSize < 8 ) || ( nRecSize & 3 ) ) // Parameters are always divisible by 4
+ {
+ bStatus = sal_False;
+ break;
+ }
+
+ nNextPos = pWMF->Tell() + ( nRecSize - 8 );
+
+ if ( !pWMF->good() || nNextPos > nEndPos )
+ {
+ bStatus = sal_False;
+ break;
+ }
+
+ if( !aBmpSaveList.empty()
+ && ( nRecType != EMR_STRETCHBLT )
+ && ( nRecType != EMR_STRETCHDIBITS )
+ )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+
+ bFlag = sal_False;
+
+ EMFP_DEBUG(printf ("0x%04x-0x%04x record type: %d size: %d\n",(unsigned int) (nNextPos - nRecSize),(unsigned int) nNextPos, (int)nRecType,(int) nRecSize));
+
+ if( bEnableEMFPlus && nRecType == EMR_GDICOMMENT ) {
+ sal_uInt32 length;
+
+ *pWMF >> length;
+
+ EMFP_DEBUG(printf ("\tGDI comment\n\t\tlength: %d\n", (int)length));
+
+ if( pWMF->good() && length >= 4 ) {
+ sal_uInt32 id;
+
+ *pWMF >> id;
+
+ EMFP_DEBUG(printf ("\t\tbegin %c%c%c%c id: 0x%x\n", (char)(id & 0xff), (char)((id & 0xff00) >> 8), (char)((id & 0xff0000) >> 16), (char)((id & 0xff000000) >> 24), (unsigned int)id));
+
+ // EMF+ comment (fixme: BE?)
+ if( id == 0x2B464D45 && nRecSize >= 12 )
+ ReadEMFPlusComment( length, bHaveDC );
+ // GDIC comment, doesn't do anything useful yet
+ else if( id == 0x43494447 && nRecSize >= 12 ) {
+ //ToDo: ReadGDIComment()
+ } else {
+ EMFP_DEBUG(printf ("\t\tunknown id: 0x%x\n",(unsigned int) id));
+ }
+ }
+ } else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
+
+ switch( nRecType )
+ {
+ case EMR_POLYBEZIERTO :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYBEZIER :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYGON :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYLINETO :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYLINE :
+ ReadAndDrawPolygon<sal_Int32>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYPOLYLINE :
+ ReadAndDrawPolyLine<sal_Int32>();
+ break;
+
+ case EMR_POLYPOLYGON :
+ ReadAndDrawPolyPolygon<sal_Int32>();
+ break;
+
+ case EMR_SETWINDOWEXTEX :
+ { // #75383#
+ *pWMF >> nW >> nH;
+ pOut->SetWinExt( Size( nW, nH ) );
+ }
+ break;
+
+ case EMR_SETWINDOWORGEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->SetWinOrg( Point( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_SCALEWINDOWEXTEX :
+ {
+ *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
+ pOut->ScaleWinExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTORGEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->SetDevOrg( Point( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_SCALEVIEWPORTEXTEX :
+ {
+ *pWMF >> nNom1 >> nDen1 >> nNom2 >> nDen2;
+ pOut->ScaleDevExt( (double)nNom1 / nDen1, (double)nNom2 / nDen2 );
+ }
+ break;
+
+ case EMR_SETVIEWPORTEXTEX :
+ {
+ *pWMF >> nW >> nH;
+ pOut->SetDevExt( Size( nW, nH ) );
+ }
+ break;
+
+ case EMR_EOF :
+ nRecordCount = 0; // #76846#
+ break;
+
+ case EMR_SETPIXELV :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->DrawPixel( Point( nX32, nY32 ), ReadColor() );
+ }
+ break;
+
+ case EMR_SETMAPMODE :
+ {
+ sal_uInt32 nMapMode;
+ *pWMF >> nMapMode;
+ pOut->SetMapMode( nMapMode );
+ }
+ break;
+
+ case EMR_SETBKMODE :
+ {
+ *pWMF >> nDat32;
+ pOut->SetBkMode( nDat32 );
+ }
+ break;
+
+ case EMR_SETPOLYFILLMODE :
+ break;
+
+ case EMR_SETROP2 :
+ {
+ *pWMF >> nDat32;
+ pOut->SetRasterOp( nDat32 );
+ }
+ break;
+
+ case EMR_SETSTRETCHBLTMODE :
+ {
+ *pWMF >> nStretchBltMode;
+ }
+ break;
+
+ case EMR_SETTEXTALIGN :
+ {
+ *pWMF >> nDat32;
+ pOut->SetTextAlign( nDat32 );
+ }
+ break;
+
+ case EMR_SETTEXTCOLOR :
+ {
+ pOut->SetTextColor( ReadColor() );
+ }
+ break;
+
+ case EMR_SETBKCOLOR :
+ {
+ pOut->SetBkColor( ReadColor() );
+ }
+ break;
+
+ case EMR_OFFSETCLIPRGN :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->MoveClipRegion( Size( nX32, nY32 ) );
+ }
+ break;
+
+ case EMR_MOVETOEX :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->MoveTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_INTERSECTCLIPRECT :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->IntersectClipRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_SAVEDC :
+ {
+ pOut->Push();
+ }
+ break;
+
+ case EMR_RESTOREDC :
+ {
+ pOut->Pop();
+ }
+ break;
+
+ case EMR_SETWORLDTRANSFORM :
+ {
+ XForm aTempXForm;
+ *pWMF >> aTempXForm;
+ pOut->SetWorldTransform( aTempXForm );
+ }
+ break;
+
+ case EMR_MODIFYWORLDTRANSFORM :
+ {
+ sal_uInt32 nMode;
+ XForm aTempXForm;
+ *pWMF >> aTempXForm >> nMode;
+ pOut->ModifyWorldTransform( aTempXForm, nMode );
+ }
+ break;
+
+ case EMR_SELECTOBJECT :
+ {
+ *pWMF >> nIndex;
+ pOut->SelectObject( nIndex );
+ }
+ break;
+
+ case EMR_CREATEPEN :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+
+ LineInfo aLineInfo;
+ sal_uInt32 nStyle;
+ Size aSize;
+ //#fdo39428 Remove SvStream operator>>(long&)
+ sal_Int32 nTmpW(0), nTmpH(0);
+
+ *pWMF >> nStyle >> nTmpW >> nTmpH;
+ aSize.Width() = nTmpW;
+ aSize.Height() = nTmpH;
+
+ if ( aSize.Width() )
+ aLineInfo.SetWidth( aSize.Width() );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+ switch( nStyle )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
+ }
+ }
+ break;
+
+ case EMR_EXTCREATEPEN :
+ {
+ sal_Int32 elpHatch;
+ sal_uInt32 offBmi, cbBmi, offBits, cbBits, nStyle, nWidth, nBrushStyle, elpNumEntries;
+ Color aColorRef;
+
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ *pWMF >> offBmi >> cbBmi >> offBits >> cbBits >> nStyle >> nWidth >> nBrushStyle;
+ aColorRef = ReadColor();
+ *pWMF >> elpHatch >> elpNumEntries;
+
+ LineInfo aLineInfo;
+ if ( nWidth )
+ aLineInfo.SetWidth( nWidth );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+
+ switch( nStyle & PS_STYLE_MASK )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( nIndex, GDI_PEN, new WinMtfLineStyle( aColorRef, aLineInfo, bTransparent ) );
+ }
+ }
+ break;
+
+ case EMR_CREATEBRUSHINDIRECT :
+ {
+ sal_uInt32 nStyle;
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ *pWMF >> nStyle;
+ pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
+ }
+ }
+ break;
+
+ case EMR_DELETEOBJECT :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ pOut->DeleteObject( nIndex );
+ }
+ break;
+
+ case EMR_ELLIPSE :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->DrawEllipse( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_RECTANGLE :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32;
+ pOut->DrawRect( ReadRectangle( nX32, nY32, nx32, ny32 ) );
+ }
+ break;
+
+ case EMR_ROUNDRECT :
+ {
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nW >> nH;
+ Size aSize( Size( nW, nH ) );
+ pOut->DrawRoundRect( ReadRectangle( nX32, nY32, nx32, ny32 ), aSize );
+ }
+ break;
+
+ case EMR_ARC :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_CHORD :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawChord( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_PIE :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ const Rectangle aRect( ReadRectangle( nX32, nY32, nx32, ny32 ));
+
+ // #i73608# OutputDevice deviates from WMF
+ // semantics. start==end means full ellipse here.
+ if( nStartX == nEndX && nStartY == nEndY )
+ pOut->DrawEllipse( aRect );
+ else
+ pOut->DrawPie( aRect, Point( nStartX, nStartY ), Point( nEndX, nEndY ) );
+ }
+ break;
+
+ case EMR_LINETO :
+ {
+ *pWMF >> nX32 >> nY32;
+ pOut->LineTo( Point( nX32, nY32 ), bRecordPath );
+ }
+ break;
+
+ case EMR_ARCTO :
+ {
+ sal_uInt32 nStartX, nStartY, nEndX, nEndY;
+ *pWMF >> nX32 >> nY32 >> nx32 >> ny32 >> nStartX >> nStartY >> nEndX >> nEndY;
+ pOut->DrawArc( ReadRectangle( nX32, nY32, nx32, ny32 ), Point( nStartX, nStartY ), Point( nEndX, nEndY ), sal_True );
+ }
+ break;
+
+ case EMR_BEGINPATH :
+ {
+ pOut->ClearPath();
+ bRecordPath = sal_True;
+ }
+ break;
+
+ case EMR_ABORTPATH :
+ pOut->ClearPath();
+ case EMR_ENDPATH :
+ bRecordPath = sal_False;
+ break;
+
+ case EMR_CLOSEFIGURE :
+ pOut->ClosePath();
+ break;
+
+ case EMR_FILLPATH :
+ pOut->StrokeAndFillPath( sal_False, sal_True );
+ break;
+
+ case EMR_STROKEANDFILLPATH :
+ pOut->StrokeAndFillPath( sal_True, sal_True );
+ break;
+
+ case EMR_STROKEPATH :
+ pOut->StrokeAndFillPath( sal_True, sal_False );
+ break;
+
+ case EMR_SELECTCLIPPATH :
+ {
+ sal_Int32 nClippingMode;
+ *pWMF >> nClippingMode;
+ pOut->SetClipPath( pOut->GetPathObj(), nClippingMode, sal_True );
+ }
+ break;
+
+ case EMR_EXTSELECTCLIPRGN :
+ {
+ sal_Int32 iMode, cbRgnData;
+ *pWMF >> cbRgnData
+ >> iMode;
+
+ PolyPolygon aPolyPoly;
+ if ( cbRgnData )
+ ImplReadRegion( aPolyPoly, *pWMF, nRecSize );
+ pOut->SetClipPath( aPolyPoly, iMode, sal_False );
+ }
+ break;
+
+ case EMR_BITBLT : // PASSTHROUGH INTENDED
+ case EMR_STRETCHBLT :
+ {
+ sal_Int32 xDest, yDest, cxDest, cyDest, xSrc, ySrc, cxSrc, cySrc;
+ sal_uInt32 dwRop, iUsageSrc, offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc;
+ XForm xformSrc;
+
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> xDest >> yDest >> cxDest >> cyDest >> dwRop >> xSrc >> ySrc
+ >> xformSrc >> nColor >> iUsageSrc >> offBmiSrc >> cbBmiSrc
+ >> offBitsSrc >> cbBitsSrc;
+
+ if ( nRecType == EMR_STRETCHBLT )
+ *pWMF >> cxSrc >> cySrc;
+ else
+ cxSrc = cySrc = 0;
+
+ Bitmap aBitmap;
+ Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+ cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
+ cyDest = abs( (int)cyDest ); // and also 122889
+
+ if ( (cbBitsSrc > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc) )
+ bStatus = sal_False;
+ else
+ {
+ sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBitsSrc
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmiSrc + 14;
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->Read( pBuf + 14, cbBmiSrc );
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+ {
+ Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+ aBitmap.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case EMR_STRETCHDIBITS :
+ {
+ sal_Int32 xDest, yDest, xSrc, ySrc, cxSrc, cySrc, cxDest, cyDest;
+ sal_uInt32 offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc, iUsageSrc, dwRop;
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> xDest
+ >> yDest
+ >> xSrc
+ >> ySrc
+ >> cxSrc
+ >> cySrc
+ >> offBmiSrc
+ >> cbBmiSrc
+ >> offBitsSrc
+ >> cbBitsSrc
+ >> iUsageSrc
+ >> dwRop
+ >> cxDest
+ >> cyDest;
+
+ Bitmap aBitmap;
+ Rectangle aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
+
+ cxDest = abs( (int)cxDest ); // sj: i37894, size can be negative
+ cyDest = abs( (int)cyDest ); // and also 122889
+
+ if ( ((SAL_MAX_UINT32 - 14) < cbBitsSrc)
+ || ((SAL_MAX_UINT32 - 14) - cbBitsSrc < cbBmiSrc )
+ )
+ {
+ bStatus = sal_False;
+ }
+ else
+ {
+ sal_uInt32 nSize = cbBmiSrc + cbBitsSrc + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBitsSrc
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmiSrc + 14;
+ pWMF->Seek( nStart + offBmiSrc );
+ pWMF->Read( pBuf + 14, cbBmiSrc );
+ pWMF->Seek( nStart + offBitsSrc );
+ pWMF->Read( pBuf + 14 + cbBmiSrc, cbBitsSrc );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+
+ // test if it is sensible to crop
+ if ( ( cxSrc > 0 ) && ( cySrc > 0 ) &&
+ ( xSrc >= 0 ) && ( ySrc >= 0 ) &&
+ ( xSrc + cxSrc <= aBitmap.GetSizePixel().Width() ) &&
+ ( ySrc + cySrc <= aBitmap.GetSizePixel().Height() ) )
+ {
+ Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
+ aBitmap.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case EMR_EXTCREATEFONTINDIRECTW :
+ {
+ *pWMF >> nIndex;
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ LOGFONTW aLogFont;
+ *pWMF >> aLogFont.lfHeight
+ >> aLogFont.lfWidth
+ >> aLogFont.lfEscapement
+ >> aLogFont.lfOrientation
+ >> aLogFont.lfWeight
+ >> aLogFont.lfItalic
+ >> aLogFont.lfUnderline
+ >> aLogFont.lfStrikeOut
+ >> aLogFont.lfCharSet
+ >> aLogFont.lfOutPrecision
+ >> aLogFont.lfClipPrecision
+ >> aLogFont.lfQuality
+ >> aLogFont.lfPitchAndFamily;
+
+ sal_Unicode lfFaceName[ LF_FACESIZE ];
+
+ for ( int i = 0; i < LF_FACESIZE; i++ )
+ {
+ sal_uInt16 nChar;
+ *pWMF >> nChar;
+ lfFaceName[ i ] = nChar;
+ }
+ aLogFont.alfFaceName = rtl::OUString( lfFaceName );
+ pOut->CreateObject( nIndex, GDI_FONT, new WinMtfFontStyle( aLogFont ) );
+ }
+ }
+ break;
+
+ case EMR_EXTTEXTOUTA :
+ bFlag = sal_True;
+ case EMR_EXTTEXTOUTW :
+ {
+ sal_Int32 nLeft, nTop, nRight, nBottom, ptlReferenceX, ptlReferenceY, nGfxMode, nXScale, nYScale;
+ sal_uInt32 nCurPos, nLen, nOffString, nOptions, offDx;
+ sal_Int32* pDX = NULL;
+
+ nCurPos = pWMF->Tell() - 8;
+
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom >> nGfxMode >> nXScale >> nYScale
+ >> ptlReferenceX >> ptlReferenceY >> nLen >> nOffString >> nOptions;
+
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> offDx;
+
+ sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
+ if ( nOptions & ETO_RTLREADING )
+ nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ pOut->SetTextLayoutMode( nTextLayoutMode );
+ DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in EMF" );
+
+ Point aPos( ptlReferenceX, ptlReferenceY );
+ if ( nLen && ( nLen < SAL_MAX_UINT32 / sizeof(sal_Int32) ) )
+ {
+ if ( offDx && (( nCurPos + offDx + nLen * 4 ) <= nNextPos ) )
+ {
+ pWMF->Seek( nCurPos + offDx );
+ if ( ( nLen * sizeof(sal_uInt32) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ pDX = new sal_Int32[ nLen ];
+ sal_uInt32 i;
+ for ( i = 0; i < nLen; i++ )
+ *pWMF >> pDX[ i ];
+ }
+ }
+ pWMF->Seek( nCurPos + nOffString );
+ String aText;
+ if ( bFlag )
+ {
+ if ( nLen <= ( nEndPos - pWMF->Tell() ) )
+ {
+ sal_Char* pBuf = new sal_Char[ nLen ];
+ pWMF->Read( pBuf, nLen );
+ aText = String( pBuf, (sal_uInt16)nLen, pOut->GetCharSet() );
+ delete[] pBuf;
+
+ if ( aText.Len() != nLen )
+ {
+ sal_uInt16 i, j;
+ sal_Int32* pOldDx = pDX;
+ pDX = new sal_Int32[ aText.Len() ];
+ for ( i = 0, j = 0; i < aText.Len(); i++ )
+ {
+ sal_Unicode cUniChar = aText.GetChar(i);
+ rtl::OString aCharacter(&cUniChar, 1, pOut->GetCharSet());
+ pDX[ i ] = 0;
+ for (sal_Int32 k = 0; ( k < aCharacter.getLength() ) && ( j < nLen ) && ( i < aText.Len() ); ++k)
+ pDX[ i ] += pOldDx[ j++ ];
+ }
+ delete[] pOldDx;
+ }
+ }
+ }
+ else
+ {
+ if ( ( nLen * sizeof(sal_Unicode) ) <= ( nEndPos - pWMF->Tell() ) )
+ {
+ sal_Unicode* pBuf = new sal_Unicode[ nLen ];
+ pWMF->Read( pBuf, nLen << 1 );
+#ifdef OSL_BIGENDIAN
+ sal_Char nTmp, *pTmp = (sal_Char*)( pBuf + nLen );
+ while ( pTmp-- != (sal_Char*)pBuf )
+ {
+ nTmp = *pTmp--;
+ pTmp[ 1 ] = *pTmp;
+ *pTmp = nTmp;
+ }
+#endif
+ aText = rtl::OUString(pBuf, nLen);
+ delete[] pBuf;
+ }
+ }
+ pOut->DrawText( aPos, aText, pDX, bRecordPath, nGfxMode );
+ }
+ delete[] pDX;
+ }
+ break;
+
+ case EMR_POLYBEZIERTO16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYBEZIER16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyBezier, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYGON16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolygon, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYLINETO16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_True);
+ break;
+ case EMR_POLYLINE16 :
+ ReadAndDrawPolygon<sal_Int16>(boost::bind(&WinMtfOutput::DrawPolyLine, _1, _2, _3, _4), sal_False);
+ break;
+
+ case EMR_POLYPOLYLINE16 :
+ ReadAndDrawPolyLine<sal_Int16>();
+ break;
+
+ case EMR_POLYPOLYGON16 :
+ ReadAndDrawPolyPolygon<sal_Int16>();
+ break;
+
+ case EMR_FILLRGN :
+ {
+ sal_uInt32 nLen;
+ PolyPolygon aPolyPoly;
+ pWMF->SeekRel( 0x10 );
+ *pWMF >> nLen >> nIndex;
+
+ if ( ImplReadRegion( aPolyPoly, *pWMF, nRecSize ) )
+ {
+ pOut->Push();
+ pOut->SelectObject( nIndex );
+ pOut->DrawPolyPolygon( aPolyPoly, sal_False );
+ pOut->Pop();
+ }
+ }
+ break;
+
+ case EMR_CREATEDIBPATTERNBRUSHPT :
+ {
+ sal_uInt32 nStart = pWMF->Tell() - 8;
+ Bitmap aBitmap;
+
+ *pWMF >> nIndex;
+
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ sal_uInt32 usage, offBmi, cbBmi, offBits, cbBits;
+
+ *pWMF >> usage;
+ *pWMF >> offBmi;
+ *pWMF >> cbBmi;
+ *pWMF >> offBits;
+ *pWMF >> cbBits;
+
+ if ( (cbBits > (SAL_MAX_UINT32 - 14)) || ((SAL_MAX_UINT32 - 14) - cbBits < cbBmi) )
+ bStatus = sal_False;
+ else if ( offBmi )
+ {
+ sal_uInt32 nSize = cbBmi + cbBits + 14;
+ if ( nSize <= ( nEndPos - nStartPos ) )
+ {
+ char* pBuf = new char[ nSize ];
+
+ SvMemoryStream aTmp( pBuf, nSize, STREAM_READ | STREAM_WRITE );
+ aTmp.ObjectOwnsMemory( sal_True );
+ aTmp << (sal_uInt8)'B'
+ << (sal_uInt8)'M'
+ << (sal_uInt32)cbBits
+ << (sal_uInt16)0
+ << (sal_uInt16)0
+ << (sal_uInt32)cbBmi + 14;
+ pWMF->Seek( nStart + offBmi );
+ pWMF->Read( pBuf + 14, cbBmi );
+ pWMF->Seek( nStart + offBits );
+ pWMF->Read( pBuf + 14 + cbBmi, cbBits );
+ aTmp.Seek( 0 );
+ aBitmap.Read( aTmp, sal_True );
+ }
+ }
+ }
+
+ pOut->CreateObject( nIndex, GDI_BRUSH, new WinMtfFillStyle( aBitmap ) );
+ }
+ break;
+
+#ifdef WIN_MTF_ASSERT
+ default : WinMtfAssertHandler( "Unknown Meta Action" ); break;
+ case EMR_MASKBLT : WinMtfAssertHandler( "MaskBlt" ); break;
+ case EMR_PLGBLT : WinMtfAssertHandler( "PlgBlt" ); break;
+ case EMR_SETDIBITSTODEVICE : WinMtfAssertHandler( "SetDIBitsToDevice" ); break;
+ case EMR_FRAMERGN : WinMtfAssertHandler( "FrameRgn" ); break;
+ case EMR_INVERTRGN : WinMtfAssertHandler( "InvertRgn" ); break;
+ case EMR_PAINTRGN : WinMtfAssertHandler( "PaintRgn" ); break;
+ case EMR_FLATTENPATH : WinMtfAssertHandler( "FlattenPath" ); break;
+ case EMR_WIDENPATH : WinMtfAssertHandler( "WidenPath" ); break;
+ case EMR_POLYDRAW : WinMtfAssertHandler( "Polydraw" ); break;
+ case EMR_SETARCDIRECTION : WinMtfAssertHandler( "SetArcDirection" ); break;
+ case EMR_SETPALETTEENTRIES : WinMtfAssertHandler( "SetPaletteEntries" ); break;
+ case EMR_RESIZEPALETTE : WinMtfAssertHandler( "ResizePalette" ); break;
+ case EMR_EXTFLOODFILL : WinMtfAssertHandler( "ExtFloodFill" ); break;
+ case EMR_ANGLEARC : WinMtfAssertHandler( "AngleArc" ); break;
+ case EMR_SETCOLORADJUSTMENT : WinMtfAssertHandler( "SetColorAdjustment" ); break;
+ case EMR_POLYDRAW16 : WinMtfAssertHandler( "PolyDraw16" ); break;
+ case EMR_POLYTEXTOUTA : WinMtfAssertHandler( "PolyTextOutA" ); break;
+ case EMR_POLYTEXTOUTW : WinMtfAssertHandler( "PolyTextOutW" ); break;
+ case EMR_CREATECOLORSPACE : WinMtfAssertHandler( "CreateColorSpace" ); break;
+ case EMR_SETCOLORSPACE : WinMtfAssertHandler( "SetColorSpace" ); break;
+ case EMR_DELETECOLORSPACE : WinMtfAssertHandler( "DeleteColorSpace" ); break;
+ case EMR_GLSRECORD : WinMtfAssertHandler( "GlsRecord" ); break;
+ case EMR_GLSBOUNDEDRECORD : WinMtfAssertHandler( "GlsBoundRecord" ); break;
+ case EMR_PIXELFORMAT : WinMtfAssertHandler( "PixelFormat" ); break;
+ case EMR_DRAWESCAPE : WinMtfAssertHandler( "DrawEscape" ); break;
+ case EMR_EXTESCAPE : WinMtfAssertHandler( "ExtEscape" ); break;
+ case EMR_STARTDOC : WinMtfAssertHandler( "StartDoc" ); break;
+ case EMR_SMALLTEXTOUT : WinMtfAssertHandler( "SmallTextOut" ); break;
+ case EMR_FORCEUFIMAPPING : WinMtfAssertHandler( "ForceUFIMapping" ); break;
+ case EMR_NAMEDESCAPE : WinMtfAssertHandler( "NamedEscape" ); break;
+ case EMR_COLORCORRECTPALETTE : WinMtfAssertHandler( "ColorCorrectPalette" ); break;
+ case EMR_SETICMPROFILEA : WinMtfAssertHandler( "SetICMProfileA" ); break;
+ case EMR_SETICMPROFILEW : WinMtfAssertHandler( "SetICMProfileW" ); break;
+ case EMR_ALPHABLEND : WinMtfAssertHandler( "Alphablend" ); break;
+ case EMR_TRANSPARENTBLT : WinMtfAssertHandler( "TransparenBlt" ); break;
+ case EMR_TRANSPARENTDIB : WinMtfAssertHandler( "TransparenDib" ); break;
+ case EMR_GRADIENTFILL : WinMtfAssertHandler( "GradientFill" ); break;
+ case EMR_SETLINKEDUFIS : WinMtfAssertHandler( "SetLinkedUFIS" ); break;
+
+ case EMR_SETMAPPERFLAGS : WinMtfAssertHandler( "SetMapperFlags", 0 ); break;
+ case EMR_SETICMMODE : WinMtfAssertHandler( "SetICMMode", 0 ); break;
+ case EMR_CREATEMONOBRUSH : WinMtfAssertHandler( "CreateMonoBrush", 0 ); break;
+ case EMR_SETBRUSHORGEX : WinMtfAssertHandler( "SetBrushOrgEx", 0 ); break;
+ case EMR_SETMETARGN : WinMtfAssertHandler( "SetMetArgn", 0 ); break;
+ case EMR_SETMITERLIMIT : WinMtfAssertHandler( "SetMiterLimit", 0 ); break;
+ case EMR_EXCLUDECLIPRECT : WinMtfAssertHandler( "ExcludeClipRect", 0 ); break;
+ case EMR_REALIZEPALETTE : WinMtfAssertHandler( "RealizePalette", 0 ); break;
+ case EMR_SELECTPALETTE : WinMtfAssertHandler( "SelectPalette", 0 ); break;
+ case EMR_CREATEPALETTE : WinMtfAssertHandler( "CreatePalette", 0 ); break;
+ case EMR_ALPHADIBBLEND : WinMtfAssertHandler( "AlphaDibBlend", 0 ); break;
+ case EMR_SETTEXTJUSTIFICATION : WinMtfAssertHandler( "SetTextJustification", 0 ); break;
+
+ case EMR_GDICOMMENT :
+ case EMR_HEADER : // has already been read at ReadHeader()
+ break;
+#endif
+ }
+ pWMF->Seek( nNextPos );
+ }
+ if( !aBmpSaveList.empty() )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+
+ if ( bStatus )
+ pWMF->Seek(nEndPos);
+
+ return bStatus;
+};
+
+//-----------------------------------------------------------------------------------
+
+sal_Bool EnhWMFReader::ReadHeader()
+{
+ sal_uInt32 nsal_uInt32, nHeaderSize, nPalEntries;
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+
+ // Spare me the METAFILEHEADER here
+ // Reading the METAHEADER
+ *pWMF >> nsal_uInt32 >> nHeaderSize;
+ if ( nsal_uInt32 != 1 ) // Type
+ return sal_False;
+
+ // bound size
+ Rectangle rclBounds; // rectangle in logical units 1/100th mm
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom;
+ rclBounds.Left() = nLeft;
+ rclBounds.Top() = nTop;
+ rclBounds.Right() = nRight;
+ rclBounds.Bottom() = nBottom;
+
+ // picture frame size
+ Rectangle rclFrame; // rectangle in device units
+ *pWMF >> nLeft >> nTop >> nRight >> nBottom;
+ rclFrame.Left() = nLeft;
+ rclFrame.Top() = nTop;
+ rclFrame.Right() = nRight;
+ rclFrame.Bottom() = nBottom;
+
+ *pWMF >> nsal_uInt32; // signature
+
+ if ( nsal_uInt32 != 0x464d4520 )
+ return sal_False;
+
+ *pWMF >> nsal_uInt32; // nVersion
+ *pWMF >> nEndPos; // size of metafile
+ nEndPos += nStartPos;
+
+ sal_uInt32 nStrmPos = pWMF->Tell(); // checking if nEndPos is valid
+ pWMF->Seek( STREAM_SEEK_TO_END );
+ if ( pWMF->Tell() < nEndPos )
+ nEndPos = pWMF->Tell();
+ pWMF->Seek( nStrmPos );
+
+ *pWMF >> nRecordCount;
+
+ if ( !nRecordCount )
+ return sal_False;
+
+ pWMF->SeekRel( 0xc );
+
+ sal_Int32 nPixX, nPixY, nMillX, nMillY;
+ *pWMF >> nPalEntries >> nPixX >> nPixY >> nMillX >> nMillY;
+
+ pOut->SetrclFrame( rclFrame );
+ pOut->SetrclBounds( rclBounds );
+ pOut->SetRefPix( Size( nPixX, nPixY ) );
+ pOut->SetRefMill( Size( nMillX, nMillY ) );
+
+ pWMF->Seek( nStartPos + nHeaderSize );
+ return sal_True;
+}
+
+//-----------------------------------------------------------------------------------
+
+Rectangle EnhWMFReader::ReadRectangle( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ Point aTL ( Point( x1, y1 ) );
+ Point aBR( Point( --x2, --y2 ) );
+ return Rectangle( aTL, aBR );
+}
+
+EnhWMFReader::~EnhWMFReader()
+{
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
new file mode 100644
index 000000000000..63b0996b24a3
--- /dev/null
+++ b/vcl/source/filter/wmf/winmtf.cxx
@@ -0,0 +1,2239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "winmtf.hxx"
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/graphictools.hxx>
+#include <vcl/canvastools.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/svapp.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/tencinfo.h>
+
+// ------------------------------------------------------------------------
+
+#if OSL_DEBUG_LEVEL > 1
+#define EMFP_DEBUG(x) x
+#else
+#define EMFP_DEBUG(x)
+#endif
+
+void WinMtfClipPath::intersectClipRect( const Rectangle& rRect )
+{
+ maClip.intersectRange(
+ vcl::unotools::b2DRectangleFromRectangle(rRect));
+}
+
+void WinMtfClipPath::excludeClipRect( const Rectangle& rRect )
+{
+ maClip.subtractRange(
+ vcl::unotools::b2DRectangleFromRectangle(rRect));
+}
+
+void WinMtfClipPath::setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode )
+{
+ const basegfx::B2DPolyPolygon& rB2DPoly=rPolyPolygon.getB2DPolyPolygon();
+ switch ( nClippingMode )
+ {
+ case RGN_OR :
+ maClip.unionPolyPolygon(rB2DPoly);
+ break;
+ case RGN_XOR :
+ maClip.xorPolyPolygon(rB2DPoly);
+ break;
+ case RGN_DIFF :
+ maClip.subtractPolyPolygon(rB2DPoly);
+ break;
+ case RGN_AND :
+ maClip.intersectPolyPolygon(rB2DPoly);
+ break;
+ case RGN_COPY :
+ maClip = basegfx::tools::B2DClipState(rB2DPoly);
+ break;
+ }
+}
+
+void WinMtfClipPath::moveClipRegion( const Size& rSize )
+{
+ // what a weird concept. emulate, don't want this in B2DClipState
+ // API
+ basegfx::B2DPolyPolygon aCurrClip=maClip.getClipPoly();
+ basegfx::B2DHomMatrix aTranslate;
+ aTranslate.translate(rSize.Width(), rSize.Height());
+
+ aCurrClip.transform(aTranslate);
+ maClip = basegfx::tools::B2DClipState( aCurrClip );
+}
+
+basegfx::B2DPolyPolygon WinMtfClipPath::getClipPath() const
+{
+ return maClip.getClipPoly();
+}
+
+// ------------------------------------------------------------------------
+
+void WinMtfPathObj::AddPoint( const Point& rPoint )
+{
+ if ( bClosed )
+ Insert( Polygon(), POLYPOLY_APPEND );
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL );
+ bClosed = sal_False;
+}
+
+void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine )
+{
+ if ( bClosed )
+ Insert( Polygon(), POLYPOLY_APPEND );
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ rPoly.Insert( rPoly.GetSize(), rPolyLine );
+ bClosed = sal_False;
+}
+
+void WinMtfPathObj::AddPolygon( const Polygon& rPoly )
+{
+ Insert( rPoly, POLYPOLY_APPEND );
+ bClosed = sal_True;
+}
+
+void WinMtfPathObj::AddPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ sal_uInt16 i, nCount = rPolyPoly.Count();
+ for ( i = 0; i < nCount; i++ )
+ Insert( rPolyPoly[ i ], POLYPOLY_APPEND );
+ bClosed = sal_True;
+}
+
+void WinMtfPathObj::ClosePath()
+{
+ if ( Count() )
+ {
+ Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ];
+ if ( rPoly.GetSize() > 2 )
+ {
+ Point aFirst( rPoly[ 0 ] );
+ if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] )
+ rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL );
+ }
+ }
+ bClosed = sal_True;
+}
+
+// ------------------------------------------------------------------------
+
+WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont )
+{
+ CharSet eCharSet;
+ if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ else
+ eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet );
+ if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ aFont.SetCharSet( eCharSet );
+ aFont.SetName( rFont.alfFaceName );
+ FontFamily eFamily;
+ switch ( rFont.lfPitchAndFamily & 0xf0 )
+ {
+ case FF_ROMAN:
+ eFamily = FAMILY_ROMAN;
+ break;
+
+ case FF_SWISS:
+ eFamily = FAMILY_SWISS;
+ break;
+
+ case FF_MODERN:
+ eFamily = FAMILY_MODERN;
+ break;
+
+ case FF_SCRIPT:
+ eFamily = FAMILY_SCRIPT;
+ break;
+
+ case FF_DECORATIVE:
+ eFamily = FAMILY_DECORATIVE;
+ break;
+
+ default:
+ eFamily = FAMILY_DONTKNOW;
+ break;
+ }
+ aFont.SetFamily( eFamily );
+
+ FontPitch ePitch;
+ switch ( rFont.lfPitchAndFamily & 0x0f )
+ {
+ case FIXED_PITCH:
+ ePitch = PITCH_FIXED;
+ break;
+
+ case DEFAULT_PITCH:
+ case VARIABLE_PITCH:
+ default:
+ ePitch = PITCH_VARIABLE;
+ break;
+ }
+ aFont.SetPitch( ePitch );
+
+ FontWeight eWeight;
+ if( rFont.lfWeight <= FW_THIN )
+ eWeight = WEIGHT_THIN;
+ else if( rFont.lfWeight <= FW_ULTRALIGHT )
+ eWeight = WEIGHT_ULTRALIGHT;
+ else if( rFont.lfWeight <= FW_LIGHT )
+ eWeight = WEIGHT_LIGHT;
+ else if( rFont.lfWeight < FW_MEDIUM )
+ eWeight = WEIGHT_NORMAL;
+ else if( rFont.lfWeight == FW_MEDIUM )
+ eWeight = WEIGHT_MEDIUM;
+ else if( rFont.lfWeight <= FW_SEMIBOLD )
+ eWeight = WEIGHT_SEMIBOLD;
+ else if( rFont.lfWeight <= FW_BOLD )
+ eWeight = WEIGHT_BOLD;
+ else if( rFont.lfWeight <= FW_ULTRABOLD )
+ eWeight = WEIGHT_ULTRABOLD;
+ else
+ eWeight = WEIGHT_BLACK;
+ aFont.SetWeight( eWeight );
+
+ if( rFont.lfItalic )
+ aFont.SetItalic( ITALIC_NORMAL );
+
+ if( rFont.lfUnderline )
+ aFont.SetUnderline( UNDERLINE_SINGLE );
+
+ if( rFont.lfStrikeOut )
+ aFont.SetStrikeout( STRIKEOUT_SINGLE );
+
+ if ( rFont.lfOrientation )
+ aFont.SetOrientation( (short)rFont.lfOrientation );
+ else
+ aFont.SetOrientation( (short)rFont.lfEscapement );
+
+ Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) );
+ if ( rFont.lfHeight > 0 )
+ {
+ // converting the cell height into a font height
+ VirtualDevice aVDev;
+ aFont.SetSize( aFontSize );
+ aVDev.SetFont( aFont );
+ FontMetric aMetric( aVDev.GetFontMetric() );
+ long nHeight = aMetric.GetAscent() + aMetric.GetDescent();
+ if ( nHeight )
+ {
+ double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight;
+ aFontSize.Height() = (sal_Int32)( fHeight + 0.5 );
+ }
+ }
+ else if ( aFontSize.Height() < 0 )
+ aFontSize.Height() *= -1;
+
+ if ( !rFont.lfWidth )
+ {
+ VirtualDevice aVDev;
+ aFont.SetSize( aFontSize );
+ aVDev.SetFont( aFont );
+ FontMetric aMetric( aVDev.GetFontMetric() );
+ aFontSize.Width() = aMetric.GetWidth();
+ }
+
+ aFont.SetSize( aFontSize );
+};
+
+// ------------------------------------------------------------------------
+
+#ifdef WIN_MTF_ASSERT
+void WinMtfAssertHandler( const sal_Char* pAction, sal_uInt32 nFlags )
+{
+ static sal_Bool bOnlyOnce;
+ static sal_Int32 nAssertCount;
+
+ if ( nFlags & WIN_MTF_ASSERT_INIT )
+ nAssertCount = 0;
+ if ( nFlags & WIN_MTF_ASSERT_ONCE )
+ bOnlyOnce = sal_True;
+ if ( nFlags & WIN_MTF_ASSERT_MIFE )
+ {
+ if ( ( nAssertCount == 0 ) || ( bOnlyOnce == sal_False ) )
+ {
+ rtl::OStringBuffer aText(RTL_CONSTASCII_STRINGPARAM(
+ "WMF/EMF Import: "));
+ if (pAction)
+ aText.append(pAction);
+ aText.append(RTL_CONSTASCII_STRINGPARAM(
+ " needs to be implemented"));
+ DBG_ASSERT( 0, aText.getStr() );
+ }
+ nAssertCount++;
+ }
+}
+#endif
+
+// ------------------------------------------------------------------------
+
+WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem ) :
+ pOut ( pWinMtfOutput ),
+ pWMF ( &rStreamWMF ),
+ pFilterConfigItem ( pConfigItem )
+{
+#ifdef WIN_MTF_ASSERT
+ // we want to assert not implemented features, but we do this
+ // only once, so that nobody is handicaped by getting too much assertions
+ // I hope this will bring more testdocuments, without support of these
+ // testdocuments the implementation of missing features won't be possible. (SJ)
+ WinMtfAssertHandler( NULL, WIN_MTF_ASSERT_INIT | WIN_MTF_ASSERT_ONCE );
+#endif
+
+ SvLockBytes *pLB = pWMF->GetLockBytes();
+ if ( pLB )
+ pLB->SetSynchronMode( sal_True );
+
+ nStartPos = pWMF->Tell();
+
+ pOut->SetDevOrg( Point() );
+ if ( pFilterConfigItem )
+ {
+ xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+WinMtf::~WinMtf()
+{
+ delete pOut;
+
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+}
+
+// ------------------------------------------------------------------------
+
+void WinMtf::Callback( sal_uInt16 nPercent )
+{
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->setValue( nPercent );
+}
+
+// ------------------------------------------------------------------------
+
+Color WinMtf::ReadColor()
+{
+ sal_uInt32 nColor;
+ *pWMF >> nColor;
+ return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) );
+};
+
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+
+Point WinMtfOutput::ImplMap( const Point& rPt )
+{
+ if ( mnWinExtX && mnWinExtY )
+ {
+ double fX = rPt.X();
+ double fY = rPt.Y();
+
+ double fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx;
+ double fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy;
+
+ if ( mnGfxMode == GM_COMPATIBLE )
+ {
+ switch( mnMapMode )
+ {
+ case MM_TEXT:
+ fX2 -= mnWinOrgX;
+ fY2 -= mnWinOrgY;
+ if( mnDevWidth != 1 || mnDevHeight != 1 ) {
+ fX2 *= 2540.0/mnUnitsPerInch;
+ fY2 *= 2540.0/mnUnitsPerInch;
+ }
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
+ fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
+
+ break;
+ case MM_LOENGLISH :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 25.40;
+ fY2 *= 25.40;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_HIENGLISH :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 2.540;
+ fY2 *= 2.540;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_LOMETRIC :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= 10;
+ fY2 *= 10;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_HIMETRIC :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ default :
+ {
+ fX2 -= mnWinOrgX;
+ fY2 -= mnWinOrgY;
+ fX2 /= mnWinExtX;
+ fY2 /= mnWinExtY;
+ fX2 *= mnDevWidth;
+ fY2 *= mnDevHeight;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY; // fX2, fY2 now in device units
+ fX2 *= (double)mnMillX * 100.0 / (double)mnPixX;
+ fY2 *= (double)mnMillY * 100.0 / (double)mnPixY;
+ }
+ break;
+ }
+ fX2 -= mrclFrame.Left();
+ fY2 -= mrclFrame.Top();
+ }
+ return Point( FRound( fX2 ), FRound( fY2 ) );
+ }
+ else
+ return Point();
+};
+
+// ------------------------------------------------------------------------
+
+Size WinMtfOutput::ImplMap( const Size& rSz )
+{
+ if ( mnWinExtX && mnWinExtY )
+ {
+ double fWidth = rSz.Width() * maXForm.eM11;
+ double fHeight = rSz.Height() * maXForm.eM22;
+
+ if ( mnGfxMode == GM_COMPATIBLE )
+ {
+ switch( mnMapMode )
+ {
+ case MM_TEXT:
+ if( mnDevWidth != 1 && mnDevHeight != 1 ) {
+ fWidth *= 2540.0/mnUnitsPerInch;
+ fHeight*= 2540.0/mnUnitsPerInch;
+ } else {
+ fWidth *= (double)mnMillX * 100 / (double)mnPixX;
+ fHeight *= (double)mnMillY * 100 / (double)mnPixY;
+ }
+ break;
+ case MM_LOENGLISH :
+ {
+ fWidth *= 25.40;
+ fHeight*=-25.40;
+ }
+ break;
+ case MM_HIENGLISH :
+ {
+ fWidth *= 2.540;
+ fHeight*=-2.540;
+ }
+ break;
+ case MM_LOMETRIC :
+ {
+ fWidth *= 10;
+ fHeight*=-10;
+ }
+ break;
+ case MM_HIMETRIC :
+ {
+ fHeight *= -1;
+ }
+ break;
+ default :
+ {
+ fWidth /= mnWinExtX;
+ fHeight /= mnWinExtY;
+ fWidth *= mnDevWidth;
+ fHeight *= mnDevHeight;
+ fWidth *= (double)mnMillX * 100 / (double)mnPixX;
+ fHeight *= (double)mnMillY * 100 / (double)mnPixY;
+ }
+ break;
+ }
+ }
+ return Size( FRound( fWidth ), FRound( fHeight ) );
+ }
+ else
+ return Size();
+}
+
+//-----------------------------------------------------------------------------------
+
+Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect )
+{
+ return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplMap( Font& rFont )
+{
+ // !!! HACK: Wir setzen die Breite jetzt immer auf Null,
+ // da OS die Breite unterschiedlich interpretieren;
+ // muss spaeter in SV portabel gemacht werden ( KA 08.02.96 )
+ Size aFontSize = ImplMap ( rFont.GetSize() );
+
+ if( aFontSize.Height() < 0 )
+ aFontSize.Height() *= -1;
+
+ rFont.SetSize( aFontSize );
+
+ if( ( mnWinExtX * mnWinExtY ) < 0 )
+ rFont.SetOrientation( 3600 - rFont.GetOrientation() );
+}
+
+//-----------------------------------------------------------------------------------
+
+Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ rPolygon[ i ] = ImplMap( rPolygon[ i ] );
+ }
+ return rPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
+PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon )
+{
+ sal_uInt16 nPolys = rPolyPolygon.Count();
+ for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ;
+ return rPolyPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SelectObject( sal_Int32 nIndex )
+{
+ GDIObj* pGDIObj = NULL;
+
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ pGDIObj = new GDIObj();
+ else
+ {
+ nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
+
+ if ( (sal_uInt32)nIndex < vGDIObj.size() )
+ pGDIObj = vGDIObj[ nIndex ];
+ }
+
+ if( pGDIObj == NULL )
+ return;
+
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ {
+ sal_uInt16 nStockId = (sal_uInt8)nIndex;
+ switch( nStockId )
+ {
+ case WHITE_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) );
+ }
+ break;
+ case LTGRAY_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) );
+ }
+ break;
+ case GRAY_BRUSH :
+ case DKGRAY_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) );
+ }
+ break;
+ case BLACK_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) );
+ }
+ break;
+ case NULL_BRUSH :
+ {
+ pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True ) );
+ }
+ break;
+ case WHITE_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) );
+ }
+ break;
+ case BLACK_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) );
+ }
+ break;
+ case NULL_PEN :
+ {
+ pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True ) );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if ( pGDIObj->pStyle )
+ {
+ switch( pGDIObj->eType )
+ {
+ case GDI_PEN :
+ maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle;
+ break;
+ case GDI_BRUSH :
+ {
+ maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle;
+ mbFillStyleSelected = sal_True;
+ }
+ break;
+ case GDI_FONT :
+ maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont;
+ break;
+ default:
+ break; // -Wall many options not handled.
+ }
+ }
+ if ( nIndex & ENHMETA_STOCK_OBJECT )
+ delete pGDIObj;
+}
+
+//-----------------------------------------------------------------------------------
+
+const Font& WinMtfOutput::GetFont() const
+{
+ return maFont;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextLayoutMode( const sal_uInt32 nTextLayoutMode )
+{
+ mnTextLayoutMode = nTextLayoutMode;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetBkMode( sal_uInt32 nMode )
+{
+ mnBkMode = nMode;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetBkColor( const Color& rColor )
+{
+ maBkColor = rColor;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextColor( const Color& rColor )
+{
+ maTextColor = rColor;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign )
+{
+ mnTextAlign = nAlign;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys )
+{
+ sal_uInt32 i = vGDIObj.size();
+ vGDIObj.resize( nNewEntrys );
+ for ( ; i < nNewEntrys ; i++ )
+ vGDIObj[ i ] = NULL;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly )
+{
+ if ( rPolyPoly.Count() )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ if ( rPolyPoly.Count() == 1 )
+ {
+ if ( rPolyPoly.IsRect() )
+ mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) );
+ else
+ {
+ Polygon aPoly( rPolyPoly[ 0 ] );
+ sal_uInt16 nCount = aPoly.GetSize();
+ if ( nCount )
+ {
+ if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] )
+ {
+ Point aPoint( aPoly[ 0 ] );
+ aPoly.Insert( nCount, aPoint );
+ }
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+ }
+ }
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) );
+ }
+}
+
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle )
+{
+ if ( pStyle )
+ {
+ if ( eType == GDI_FONT )
+ {
+ ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
+ if (!((WinMtfFontStyle*)pStyle)->aFont.GetHeight() )
+ ((WinMtfFontStyle*)pStyle)->aFont.SetHeight( 423 ); // defaulting to 12pt
+ }
+ else if ( eType == GDI_PEN )
+ {
+ Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
+ if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
+ {
+ aSize.Width() += 1;
+ long nDotLen = ImplMap( aSize ).Width();
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
+ }
+ }
+ }
+ sal_uInt32 nIndex;
+ for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ )
+ {
+ if ( vGDIObj[ nIndex ] == NULL )
+ break;
+ }
+ if ( nIndex == vGDIObj.size() )
+ ImplResizeObjectArry( vGDIObj.size() + 16 );
+
+ vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pStyle )
+{
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen
+ if ( pStyle )
+ {
+ if ( eType == GDI_FONT )
+ ImplMap( ((WinMtfFontStyle*)pStyle)->aFont );
+ else if ( eType == GDI_PEN )
+ {
+ Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() );
+ if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH )
+ {
+ aSize.Width() += 1;
+ long nDotLen = ImplMap( aSize ).Width();
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen );
+ ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 );
+ }
+ }
+ }
+ if ( (sal_uInt32)nIndex >= vGDIObj.size() )
+ ImplResizeObjectArry( nIndex + 16 );
+
+ if ( vGDIObj[ nIndex ] != NULL )
+ delete vGDIObj[ nIndex ];
+
+ vGDIObj[ nIndex ] = new GDIObj( eType, pStyle );
+ }
+ else
+ {
+ switch ( eType )
+ {
+ case GDI_PEN :
+ delete (WinMtfLineStyle*)pStyle;
+ break;
+ case GDI_BRUSH :
+ delete (WinMtfFillStyle*)pStyle;
+ break;
+ case GDI_FONT :
+ delete (WinMtfFontStyle*)pStyle;
+ break;
+
+ default:
+ OSL_FAIL( "unsupported style not deleted" );
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
+{
+ if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 )
+ {
+ if ( (sal_uInt32)nIndex < vGDIObj.size() )
+ {
+ delete vGDIObj[ nIndex ];
+ vGDIObj[ nIndex ] = NULL;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.intersectClipRect( ImplMap( rRect ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.excludeClipRect( ImplMap( rRect ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::MoveClipRegion( const Size& rSize )
+{
+ mbClipNeedsUpdate=true;
+ aClipPath.moveClipRegion( ImplMap( rSize ) );
+}
+
+void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped )
+{
+ mbClipNeedsUpdate=true;
+ if ( bIsMapped )
+ aClipPath.setClipPath( rPolyPolygon, nClippingMode );
+ else
+ {
+ PolyPolygon aPP( rPolyPolygon );
+ aClipPath.setClipPath( ImplMap( aPP ), nClippingMode );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------
+
+WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
+ mnLatestTextAlign ( 0 ),
+ mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ),
+ maLatestBkColor ( 0x12345678 ),
+ maBkColor ( COL_WHITE ),
+ mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ),
+ mnTextLayoutMode ( TEXT_LAYOUT_DEFAULT ),
+ mnLatestBkMode ( 0 ),
+ mnBkMode ( OPAQUE ),
+ meLatestRasterOp ( ROP_INVERT ),
+ meRasterOp ( ROP_OVERPAINT ),
+ maActPos ( Point() ),
+ mbNopMode ( sal_False ),
+ mbFillStyleSelected ( sal_False ),
+ mbClipNeedsUpdate ( true ),
+ mbComplexClip ( false ),
+ mnGfxMode ( GM_COMPATIBLE ),
+ mnMapMode ( MM_TEXT ),
+ mnUnitsPerInch ( 96 ),
+ mnDevOrgX ( 0 ),
+ mnDevOrgY ( 0 ),
+ mnDevWidth ( 1 ),
+ mnDevHeight ( 1 ),
+ mnWinOrgX ( 0 ),
+ mnWinOrgY ( 0 ),
+ mnWinExtX ( 1 ),
+ mnWinExtY ( 1 ),
+ mnPixX ( 100 ),
+ mnPixY ( 100 ),
+ mnMillX ( 1 ),
+ mnMillY ( 1 ),
+ mpGDIMetaFile ( &rGDIMetaFile )
+{
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top
+ // of the stack so it can always be restored
+ // this is necessary to be able to support
+ // SetClipRgn( NULL ) and similar ClipRgn actions (SJ)
+
+ maFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Arial" )) ); // sj: #i57205#, we do have some scaling problems if using
+ maFont.SetCharSet( RTL_TEXTENCODING_MS_1252 ); // the default font then most times a x11 font is used, we
+ maFont.SetHeight( 423 ); // will prevent this defining a font
+
+ maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 );
+ maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 );
+
+ mnRop = R2_BLACK + 1;
+ SetRasterOp( R2_BLACK );
+};
+
+//-----------------------------------------------------------------------------------
+
+WinMtfOutput::~WinMtfOutput()
+{
+ mpGDIMetaFile->AddAction( new MetaPopAction() );
+ mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM );
+ if ( mrclFrame.IsEmpty() )
+ mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) );
+ else
+ mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() );
+
+ for ( sal_uInt32 i = 0; i < vGDIObj.size(); i++ )
+ delete vGDIObj[ i ];
+};
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateClipRegion()
+{
+ if ( mbClipNeedsUpdate )
+ {
+ mbClipNeedsUpdate = false;
+ mbComplexClip = false;
+
+ mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); //
+
+ // skip for 'no clipping at all' case
+ if( !aClipPath.isEmpty() )
+ {
+ const basegfx::B2DPolyPolygon& rClipPoly( aClipPath.getClipPath() );
+ mpGDIMetaFile->AddAction(
+ new MetaISectRectClipRegionAction(
+ vcl::unotools::rectangleFromB2DRectangle(
+ rClipPoly.getB2DRange())));
+
+ mbComplexClip = rClipPoly.count() > 1
+ || !basegfx::tools::isRectangle(rClipPoly);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz()
+{
+ Color aColor( COL_TRANSPARENT);
+ WinMtfLineStyle aTransparentLine( aColor, sal_True );
+ if ( ! ( maLatestLineStyle == aTransparentLine ) )
+ {
+ maLatestLineStyle = aTransparentLine;
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateLineStyle()
+{
+ if (!( maLatestLineStyle == maLineStyle ) )
+ {
+ maLatestLineStyle = maLineStyle;
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::UpdateFillStyle()
+{
+ if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected
+ maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == TRANSPARENT );
+ if (!( maLatestFillStyle == maFillStyle ) )
+ {
+ maLatestFillStyle = maFillStyle;
+ if (maFillStyle.aType == FillStyleSolid)
+ mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+sal_uInt32 WinMtfOutput::SetRasterOp( sal_uInt32 nRasterOp )
+{
+ sal_uInt32 nRetROP = mnRop;
+ if ( nRasterOp != mnRop )
+ {
+ mnRop = nRasterOp;
+ static WinMtfFillStyle aNopFillStyle;
+ static WinMtfLineStyle aNopLineStyle;
+
+ if ( mbNopMode && ( nRasterOp != R2_NOP ) )
+ { // beim uebergang von R2_NOP auf anderen Modus
+ // gesetzten Pen und Brush aktivieren
+ maFillStyle = aNopFillStyle;
+ maLineStyle = aNopLineStyle;
+ mbNopMode = sal_False;
+ }
+ switch( nRasterOp )
+ {
+ case R2_NOT:
+ meRasterOp = ROP_INVERT;
+ break;
+
+ case R2_XORPEN:
+ meRasterOp = ROP_XOR;
+ break;
+
+ case R2_NOP:
+ {
+ meRasterOp = ROP_OVERPAINT;
+ if( mbNopMode == sal_False )
+ {
+ aNopFillStyle = maFillStyle;
+ aNopLineStyle = maLineStyle;
+ maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True );
+ maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True );
+ mbNopMode = sal_True;
+ }
+ }
+ break;
+
+ default:
+ meRasterOp = ROP_OVERPAINT;
+ break;
+ }
+ }
+ if ( nRetROP != nRasterOp )
+ mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
+ return nRetROP;
+};
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill )
+{
+ if ( aPathObj.Count() )
+ {
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+ if ( bFill )
+ {
+ if ( !bStroke )
+ {
+ mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_LINECOLOR ) );
+ mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) );
+ }
+ if ( aPathObj.Count() == 1 )
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) );
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) );
+
+ if ( !bStroke )
+ mpGDIMetaFile->AddAction( new MetaPopAction() );
+ }
+ else
+ {
+ sal_uInt16 i, nCount = aPathObj.Count();
+ for ( i = 0; i < nCount; i++ )
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) );
+ }
+ ClearPath();
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor )
+{
+ mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath )
+{
+ Point aDest( ImplMap( rPoint ) );
+ if ( bRecordPath )
+ {
+ // fdo#57353 create new subpath for subsequent moves
+ if ( aPathObj.Count() )
+ if ( aPathObj[ aPathObj.Count() - 1 ].GetSize() )
+ aPathObj.Insert( Polygon(), POLYPOLY_APPEND );
+ aPathObj.AddPoint( aDest );
+ }
+ maActPos = aDest;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ Point aDest( ImplMap( rPoint ) );
+ if ( bRecordPath )
+ aPathObj.AddPoint( aDest );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) );
+ }
+ maActPos = aDest;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawRect( const Rectangle& rRect, sal_Bool bEdge )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ Polygon aPoly( ImplMap( rRect ) );
+ PolyPolygon aPolyPolyRect( aPoly );
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPolyRect, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ if ( bEdge )
+ {
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ }
+ }
+ else
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize )
+{
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+ mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawEllipse( const Rectangle& rRect )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ Point aCenter( ImplMap( rRect.Center() ) );
+ Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) );
+
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, sal_Bool bTo )
+{
+ UpdateClipRegion();
+ UpdateLineStyle();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ if ( aStart == aEnd )
+ { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse
+ Point aCenter( aRect.Center() );
+ Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 );
+
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) );
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) );
+ }
+ else
+ mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) );
+
+ if ( bTo )
+ maActPos = aEnd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd )
+{
+ UpdateClipRegion();
+ UpdateFillStyle();
+
+ Rectangle aRect( ImplMap( rRect ) );
+ Point aStart( ImplMap( rStart ) );
+ Point aEnd( ImplMap( rEnd ) );
+
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+ ImplMap( rPolygon );
+ if ( bRecordPath )
+ aPathObj.AddPolygon( rPolygon );
+ else
+ {
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ PolyPolygon aPolyPoly( rPolygon );
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( aPolyPoly, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) )
+ {
+ sal_uInt16 nCount = rPolygon.GetSize();
+ if ( nCount )
+ {
+ if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] )
+ {
+ Point aPoint( rPolygon[ 0 ] );
+ rPolygon.Insert( nCount, aPoint );
+ }
+ }
+ ImplSetNonPersistentLineColorTransparenz();
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+ else
+ {
+ UpdateLineStyle();
+
+ if (maLatestFillStyle.aType != FillStylePattern)
+ mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) );
+ else {
+ SvtGraphicFill aFill = SvtGraphicFill( PolyPolygon( rPolygon ),
+ Color(),
+ 0.0,
+ SvtGraphicFill::fillNonZero,
+ SvtGraphicFill::fillTexture,
+ SvtGraphicFill::Transform(),
+ true,
+ SvtGraphicFill::hatchSingle,
+ Color(),
+ SvtGraphicFill::gradientLinear,
+ Color(),
+ Color(),
+ 0,
+ Graphic (maLatestFillStyle.aBmp) );
+
+ SvMemoryStream aMemStm;
+
+ aMemStm << aFill;
+
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_BEGIN", 0,
+ static_cast<const sal_uInt8*>(aMemStm.GetData()),
+ aMemStm.Seek( STREAM_SEEK_TO_END ) ) );
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "XPATHFILL_SEQ_END" ) );
+ }
+
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ ImplMap( rPolyPolygon );
+
+ if ( bRecordPath )
+ aPathObj.AddPolyPolygon( rPolyPolygon );
+ else
+ {
+ UpdateFillStyle();
+
+ if ( mbComplexClip )
+ {
+ PolyPolygon aDest;
+ PolyPolygon(aClipPath.getClipPath()).GetIntersection( rPolyPolygon, aDest );
+ ImplDrawClippedPolyPolygon( aDest );
+ }
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ ImplMap( rPolygon );
+ if ( bTo )
+ {
+ rPolygon[ 0 ] = maActPos;
+ maActPos = rPolygon[ rPolygon.GetSize() - 1 ];
+ }
+ if ( bRecordPath )
+ aPathObj.AddPolyLine( rPolygon );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath )
+{
+ UpdateClipRegion();
+
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) )
+ {
+ ImplMap( rPolygon );
+ if ( bTo )
+ {
+ rPolygon[ 0 ] = maActPos;
+ maActPos = rPolygon[ nPoints - 1 ];
+ }
+ sal_uInt16 i;
+ for ( i = 0; ( i + 2 ) < nPoints; )
+ {
+ rPolygon.SetFlags( i++, POLY_NORMAL );
+ rPolygon.SetFlags( i++, POLY_CONTROL );
+ rPolygon.SetFlags( i++, POLY_CONTROL );
+ }
+ if ( bRecordPath )
+ aPathObj.AddPolyLine( rPolygon );
+ else
+ {
+ UpdateLineStyle();
+ mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry, sal_Bool bRecordPath, sal_Int32 nGfxMode )
+{
+ UpdateClipRegion();
+
+ VirtualDevice* pVDev = NULL;
+
+ rPosition = ImplMap( rPosition );
+
+ sal_Int32 nOldGfxMode = GetGfxMode();
+ SetGfxMode( GM_COMPATIBLE );
+ if ( pDXArry )
+ {
+ sal_Int32 i, nSum, nLen = rText.Len();
+
+ for( i = 0, nSum = 0; i < nLen; i++ )
+ {
+ if ( i ) {
+ pDXArry[ i - 1 ] = ImplMap( Size( nSum, 0 ) ).Width();
+ }
+ nSum += pDXArry[ i ];
+ }
+ }
+ if ( mnLatestTextLayoutMode != mnTextLayoutMode )
+ {
+ mnLatestTextLayoutMode = mnTextLayoutMode;
+ mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) );
+ }
+ SetGfxMode( nGfxMode );
+ sal_Bool bChangeFont = sal_False;
+ if ( mnLatestTextAlign != mnTextAlign )
+ {
+ bChangeFont = sal_True;
+ mnLatestTextAlign = mnTextAlign;
+ TextAlign eTextAlign;
+ if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
+ eTextAlign = ALIGN_BASELINE;
+ else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
+ eTextAlign = ALIGN_BOTTOM;
+ else
+ eTextAlign = ALIGN_TOP;
+ mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) );
+ }
+ if ( maLatestTextColor != maTextColor )
+ {
+ bChangeFont = sal_True;
+ maLatestTextColor = maTextColor;
+ mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) );
+ }
+ sal_Bool bChangeFillColor = sal_False;
+ if ( maLatestBkColor != maBkColor )
+ {
+ bChangeFillColor = sal_True;
+ maLatestBkColor = maBkColor;
+ }
+ if ( mnLatestBkMode != mnBkMode )
+ {
+ bChangeFillColor = sal_True;
+ mnLatestBkMode = mnBkMode;
+ }
+ if ( bChangeFillColor )
+ {
+ bChangeFont = sal_True;
+ mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) );
+ }
+ Font aTmp( maFont );
+ aTmp.SetColor( maTextColor );
+ aTmp.SetFillColor( maBkColor );
+
+ if( mnBkMode == TRANSPARENT )
+ aTmp.SetTransparent( sal_True );
+ else
+ aTmp.SetTransparent( sal_False );
+
+ if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE )
+ aTmp.SetAlign( ALIGN_BASELINE );
+ else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM )
+ aTmp.SetAlign( ALIGN_BOTTOM );
+ else
+ aTmp.SetAlign( ALIGN_TOP );
+
+ if ( nGfxMode == GM_ADVANCED )
+ {
+ // check whether there is a font rotation applied via transformation
+ Point aP1( ImplMap( Point() ) );
+ Point aP2( ImplMap( Point( 0, 100 ) ) );
+ aP2.X() -= aP1.X();
+ aP2.Y() -= aP1.Y();
+ double fX = aP2.X();
+ double fY = aP2.Y();
+ if ( fX )
+ {
+ double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308;
+ if ( fY > 0 )
+ fOrientation = 360 - fOrientation;
+ fOrientation += 90;
+ fOrientation *= 10;
+ fOrientation += aTmp.GetOrientation();
+ aTmp.SetOrientation( sal_Int16( fOrientation ) );
+ }
+ }
+
+ if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) )
+ {
+ if ( !pVDev )
+ pVDev = new VirtualDevice;
+ sal_Int32 nTextWidth;
+ pVDev->SetMapMode( MapMode( MAP_100TH_MM ) );
+ pVDev->SetFont( maFont );
+ if( pDXArry )
+ {
+ sal_uInt32 nLen = rText.Len();
+ nTextWidth = pVDev->GetTextWidth( rtl::OUString(rText.GetChar( (sal_uInt16)( nLen - 1 ) )) );
+ if( nLen > 1 )
+ nTextWidth += pDXArry[ nLen - 2 ];
+ }
+ else
+ nTextWidth = pVDev->GetTextWidth( rText );
+
+ if( mnTextAlign & TA_UPDATECP )
+ rPosition = maActPos;
+
+ if ( mnTextAlign & TA_RIGHT_CENTER )
+ {
+ double fLenght = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1;
+ rPosition.X() -= (sal_Int32)( fLenght * cos( maFont.GetOrientation() * F_PI1800 ) );
+ rPosition.Y() -= (sal_Int32)(-( fLenght * sin( maFont.GetOrientation() * F_PI1800 ) ) );
+ }
+
+ if( mnTextAlign & TA_UPDATECP )
+ maActPos.X() = rPosition.X() + nTextWidth;
+ }
+ if ( bChangeFont || ( maLatestFont != aTmp ) )
+ {
+ maLatestFont = aTmp;
+ mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) );
+ mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) );
+ mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) );
+ mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) );
+ }
+ if ( bRecordPath )
+ {
+ // ToDo
+ }
+ else
+ {
+ /* because text without dx array is badly scaled, we
+ will create such an array if necessary */
+ sal_Int32* pDX = pDXArry;
+ if ( !pDXArry )
+ {
+ SolarMutexGuard aGuard;
+
+ pDX = new sal_Int32[ rText.Len() ];
+ if ( !pVDev )
+ pVDev = new VirtualDevice;
+ pVDev->SetMapMode( MAP_100TH_MM );
+ pVDev->SetFont( maLatestFont );
+ pVDev->GetTextArray( rText, pDX, 0, STRING_LEN );
+ }
+ mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, STRING_LEN ) );
+ if ( !pDXArry ) // this means we have created our own array
+ delete[] pDX; // which must be deleted
+ }
+ SetGfxMode( nOldGfxMode );
+ delete pVDev;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap )
+{
+ BitmapEx aBmpEx( rBitmap );
+ if ( mbComplexClip )
+ {
+ VirtualDevice aVDev;
+ MapMode aMapMode( MAP_100TH_MM );
+ aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) );
+ const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) );
+ const Size aSizePixel( rBitmap.GetSizePixel() );
+ if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() )
+ {
+ aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) );
+ aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) );
+ }
+ aVDev.SetMapMode( aMapMode );
+ aVDev.SetOutputSizePixel( aSizePixel );
+ aVDev.SetFillColor( Color( COL_BLACK ) );
+ const PolyPolygon aClip( aClipPath.getClipPath() );
+ aVDev.DrawPolyPolygon( aClip );
+ const Point aEmptyPoint;
+
+ // #i50672# Extract whole VDev content (to match size of rBitmap)
+ aVDev.EnableMapMode( sal_False );
+ Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) );
+
+ if ( aBmpEx.IsTransparent() )
+ {
+ if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) )
+ aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR );
+ else
+ aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND );
+ aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
+ }
+ else
+ aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask );
+ }
+ if ( aBmpEx.IsTransparent() )
+ mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) );
+ else
+ mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ResolveBitmapActions( BSaveStructList_impl& rSaveList )
+{
+ UpdateClipRegion();
+
+ size_t nObjects = rSaveList.size();
+ size_t nObjectsLeft = nObjects;
+
+ while ( nObjectsLeft )
+ {
+ size_t i;
+ size_t nObjectsOfSameSize = 0;
+ size_t nObjectStartIndex = nObjects - nObjectsLeft;
+
+ BSaveStruct* pSave = rSaveList[ nObjectStartIndex ];
+ Rectangle aRect( pSave->aOutRect );
+
+ for ( i = nObjectStartIndex; i < nObjects; )
+ {
+ nObjectsOfSameSize++;
+ if ( ++i < nObjects )
+ {
+ pSave = rSaveList[ i ];
+ if ( pSave->aOutRect != aRect )
+ break;
+ }
+ }
+ Point aPos( ImplMap( aRect.TopLeft() ) );
+ Size aSize( ImplMap( aRect.GetSize() ) );
+
+ for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ )
+ {
+ pSave = rSaveList[ i ];
+
+ sal_uInt32 nWinRop = pSave->nWinRop;
+ sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 );
+
+ sal_uInt32 nUsed = 0;
+ if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
+ nUsed |= 1; // pattern is used
+ if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
+ nUsed |= 2; // source is used
+ if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
+ nUsed |= 4; // destination is used
+
+ if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop != PATINVERT )
+ { // patterns aren't well supported yet
+ sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT ); // in this case nRasterOperation is either 0 or 0xff
+ UpdateFillStyle();
+ DrawRect( aRect, sal_False );
+ SetRasterOp( nOldRop );
+ }
+ else
+ {
+ sal_Bool bDrawn = sal_False;
+
+ if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap
+ {
+ if ( nObjectsOfSameSize == 2 )
+ {
+ BSaveStruct* pSave2 = rSaveList[ i + 1 ];
+ if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) &&
+ ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) )
+ {
+ // TODO: Strictly speaking, we should
+ // check whether mask is monochrome, and
+ // whether image is black (upper branch)
+ // or white (lower branch). Otherwise, the
+ // effect is not the same as a masked
+ // bitmap.
+ if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) )
+ {
+ Bitmap aMask( pSave->aBmp ); aMask.Invert();
+ BitmapEx aBmpEx( pSave2->aBmp, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ bDrawn = sal_True;
+ i++;
+ }
+ // #i20085# This is just the other way
+ // around as above. Only difference: mask
+ // is inverted
+ else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) )
+ {
+ Bitmap aMask( pSave->aBmp );
+ BitmapEx aBmpEx( pSave2->aBmp, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ bDrawn = sal_True;
+ i++;
+ }
+ }
+ }
+ }
+
+ if ( !bDrawn )
+ {
+ Push();
+ sal_uInt32 nOldRop = SetRasterOp( R2_COPYPEN );
+ Bitmap aBitmap( pSave->aBmp );
+ sal_uInt32 nOperation = ( nRasterOperation & 0xf );
+ switch( nOperation )
+ {
+ case 0x1 :
+ case 0xe :
+ {
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ SetRasterOp( R2_COPYPEN );
+ Bitmap aMask( aBitmap );
+ aMask.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ if ( nOperation == 0x1 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+ case 0x7 :
+ case 0x8 :
+ {
+ Bitmap aMask( aBitmap );
+ if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used
+ {
+ aBitmap.Convert( BMP_CONVERSION_24BIT );
+ aBitmap.Erase( maFillStyle.aFillColor );
+ }
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ if ( nOperation == 0x7 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x4 :
+ case 0xb :
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ SetRasterOp( R2_COPYPEN );
+ Bitmap aMask( aBitmap );
+ aBitmap.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0xb )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x2 :
+ case 0xd :
+ {
+ Bitmap aMask( aBitmap );
+ aMask.Invert();
+ BitmapEx aBmpEx( aBitmap, aMask );
+ ImplDrawBitmap( aPos, aSize, aBmpEx );
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0xd )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+ case 0x6 :
+ case 0x9 :
+ {
+ SetRasterOp( R2_XORPEN );
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ if ( nOperation == 0x9 )
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ }
+ break;
+
+ case 0x0 : // WHITENESS
+ case 0xf : // BLACKNESS
+ { // in this case nRasterOperation is either 0 or 0xff
+ maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) );
+ UpdateFillStyle();
+ DrawRect( aRect, sal_False );
+ }
+ break;
+
+ case 0x3 : // only source is used
+ case 0xc :
+ {
+ if ( nRasterOperation == 0x33 )
+ aBitmap.Invert();
+ ImplDrawBitmap( aPos, aSize, aBitmap );
+ }
+ break;
+
+ case 0x5 : // only destination is used
+ {
+ SetRasterOp( R2_NOT );
+ DrawRect( aRect, sal_False );
+ }
+ case 0xa : // no operation
+ break;
+ }
+ SetRasterOp( nOldRop );
+ Pop();
+ }
+ }
+ }
+ nObjectsLeft -= nObjectsOfSameSize;
+ }
+
+ for( size_t i = 0, n = rSaveList.size(); i < n; ++i )
+ delete rSaveList[ i ];
+ rSaveList.clear();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevOrg( const Point& rPoint )
+{
+ mnDevOrgX = rPoint.X();
+ mnDevOrgY = rPoint.Y();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
+{
+ mnDevOrgX += nXAdd;
+ mnDevOrgY += nYAdd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetDevExt( const Size& rSize )
+{
+ if ( rSize.Width() && rSize.Height() )
+ {
+ switch( mnMapMode )
+ {
+ case MM_ISOTROPIC :
+ case MM_ANISOTROPIC :
+ {
+ mnDevWidth = rSize.Width();
+ mnDevHeight = rSize.Height();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ScaleDevExt( double fX, double fY )
+{
+ mnDevWidth = FRound( mnDevWidth * fX );
+ mnDevHeight = FRound( mnDevHeight * fY );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinOrg( const Point& rPoint )
+{
+ mnWinOrgX = rPoint.X();
+ mnWinOrgY = rPoint.Y();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
+{
+ mnWinOrgX += nXAdd;
+ mnWinOrgY += nYAdd;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWinExt( const Size& rSize )
+{
+
+ if( rSize.Width() && rSize.Height() )
+ {
+ switch( mnMapMode )
+ {
+ case MM_ISOTROPIC :
+ case MM_ANISOTROPIC :
+ {
+ mnWinExtX = rSize.Width();
+ mnWinExtY = rSize.Height();
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ScaleWinExt( double fX, double fY )
+{
+ mnWinExtX = FRound( mnWinExtX * fX );
+ mnWinExtY = FRound( mnWinExtY * fY );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetrclBounds( const Rectangle& rRect )
+{
+ mrclBounds = rRect;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetrclFrame( const Rectangle& rRect )
+{
+ mrclFrame = rRect;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetRefPix( const Size& rSize )
+{
+ mnPixX = rSize.Width();
+ mnPixY = rSize.Height();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetRefMill( const Size& rSize )
+{
+ mnMillX = rSize.Width();
+ mnMillY = rSize.Height();
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode )
+{
+ mnMapMode = nMapMode;
+ if ( nMapMode == MM_TEXT )
+ {
+ mnWinExtX = mnDevWidth;
+ mnWinExtY = mnDevHeight;
+ }
+ else if ( mnMapMode == MM_HIMETRIC )
+ {
+ mnWinExtX = mnMillX * 100;
+ mnWinExtY = mnMillY * 100;
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetUnitsPerInch( sal_uInt16 nUnitsPerInch )
+{
+ if( nUnitsPerInch != 0 )
+ mnUnitsPerInch = nUnitsPerInch;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::SetWorldTransform( const XForm& rXForm )
+{
+ maXForm.eM11 = rXForm.eM11;
+ maXForm.eM12 = rXForm.eM12;
+ maXForm.eM21 = rXForm.eM21;
+ maXForm.eM22 = rXForm.eM22;
+ maXForm.eDx = rXForm.eDx;
+ maXForm.eDy = rXForm.eDy;
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode )
+{
+ switch( nMode )
+ {
+ case MWT_IDENTITY :
+ {
+ maXForm.eM11 = maXForm.eM12 = maXForm.eM21 = maXForm.eM22 = 1.0f;
+ maXForm.eDx = maXForm.eDy = 0.0f;
+ }
+ break;
+
+ case MWT_RIGHTMULTIPLY :
+ case MWT_LEFTMULTIPLY :
+ {
+ const XForm* pLeft;
+ const XForm* pRight;
+
+ if ( nMode == MWT_LEFTMULTIPLY )
+ {
+ pLeft = &rXForm;
+ pRight = &maXForm;
+ }
+ else
+ {
+ pLeft = &maXForm;
+ pRight = &rXForm;
+ }
+
+ float aF[3][3];
+ float bF[3][3];
+ float cF[3][3];
+
+ aF[0][0] = pLeft->eM11;
+ aF[0][1] = pLeft->eM12;
+ aF[0][2] = 0;
+ aF[1][0] = pLeft->eM21;
+ aF[1][1] = pLeft->eM22;
+ aF[1][2] = 0;
+ aF[2][0] = pLeft->eDx;
+ aF[2][1] = pLeft->eDy;
+ aF[2][2] = 1;
+
+ bF[0][0] = pRight->eM11;
+ bF[0][1] = pRight->eM12;
+ bF[0][2] = 0;
+ bF[1][0] = pRight->eM21;
+ bF[1][1] = pRight->eM22;
+ bF[1][2] = 0;
+ bF[2][0] = pRight->eDx;
+ bF[2][1] = pRight->eDy;
+ bF[2][2] = 1;
+
+ int i, j, k;
+ for ( i = 0; i < 3; i++ )
+ {
+ for ( j = 0; j < 3; j++ )
+ {
+ cF[i][j] = 0;
+ for ( k = 0; k < 3; k++ )
+ cF[i][j] += aF[i][k] * bF[k][j];
+ }
+ }
+ maXForm.eM11 = cF[0][0];
+ maXForm.eM12 = cF[0][1];
+ maXForm.eM21 = cF[1][0];
+ maXForm.eM22 = cF[1][1];
+ maXForm.eDx = cF[2][0];
+ maXForm.eDy = cF[2][1];
+ }
+ break;
+ }
+ }
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it
+{ // is not allowed to use the MetaPushAction()
+ UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ)
+ SaveStructPtr pSave( new SaveStruct );
+
+ pSave->aLineStyle = maLineStyle;
+ pSave->aFillStyle = maFillStyle;
+
+ pSave->aFont = maFont;
+ pSave->aTextColor = maTextColor;
+ pSave->nTextAlign = mnTextAlign;
+ pSave->nTextLayoutMode = mnTextLayoutMode;
+ pSave->nMapMode = mnMapMode;
+ pSave->nGfxMode = mnGfxMode;
+ pSave->nBkMode = mnBkMode;
+ pSave->aBkColor = maBkColor;
+ pSave->bFillStyleSelected = mbFillStyleSelected;
+
+ pSave->aActPos = maActPos;
+ pSave->aXForm = maXForm;
+ pSave->eRasterOp = meRasterOp;
+
+ pSave->nWinOrgX = mnWinOrgX;
+ pSave->nWinOrgY = mnWinOrgY;
+ pSave->nWinExtX = mnWinExtX;
+ pSave->nWinExtY = mnWinExtY;
+ pSave->nDevOrgX = mnDevOrgX;
+ pSave->nDevOrgY = mnDevOrgY;
+ pSave->nDevWidth = mnDevWidth;
+ pSave->nDevHeight = mnDevHeight;
+
+ pSave->aPathObj = aPathObj;
+ pSave->aClipPath = aClipPath;
+
+ vSaveStack.push_back( pSave );
+}
+
+//-----------------------------------------------------------------------------------
+
+void WinMtfOutput::Pop()
+{
+ // Die aktuellen Daten vom Stack holen
+ if( !vSaveStack.empty() )
+ {
+ // Die aktuelle Daten auf dem Stack sichern
+ SaveStructPtr pSave( vSaveStack.back() );
+
+ maLineStyle = pSave->aLineStyle;
+ maFillStyle = pSave->aFillStyle;
+
+ maFont = pSave->aFont;
+ maTextColor = pSave->aTextColor;
+ mnTextAlign = pSave->nTextAlign;
+ mnTextLayoutMode = pSave->nTextLayoutMode;
+ mnBkMode = pSave->nBkMode;
+ mnGfxMode = pSave->nGfxMode;
+ mnMapMode = pSave->nMapMode;
+ maBkColor = pSave->aBkColor;
+ mbFillStyleSelected = pSave->bFillStyleSelected;
+
+ maActPos = pSave->aActPos;
+ maXForm = pSave->aXForm;
+ meRasterOp = pSave->eRasterOp;
+
+ mnWinOrgX = pSave->nWinOrgX;
+ mnWinOrgY = pSave->nWinOrgY;
+ mnWinExtX = pSave->nWinExtX;
+ mnWinExtY = pSave->nWinExtY;
+ mnDevOrgX = pSave->nDevOrgX;
+ mnDevOrgY = pSave->nDevOrgY;
+ mnDevWidth = pSave->nDevWidth;
+ mnDevHeight = pSave->nDevHeight;
+
+ aPathObj = pSave->aPathObj;
+ if ( ! ( aClipPath == pSave->aClipPath ) )
+ {
+ aClipPath = pSave->aClipPath;
+ mbClipNeedsUpdate = true;
+ }
+ if ( meLatestRasterOp != meRasterOp )
+ mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) );
+ vSaveStack.pop_back();
+ }
+}
+
+void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile )
+{
+ rGDIMetaFile.Play( *mpGDIMetaFile, 0xFFFFFFFF );
+}
+
+void WinMtfOutput::PassEMFPlusHeaderInfo()
+{
+ EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS header info\n"));
+
+ SvMemoryStream mem;
+ sal_Int32 nLeft, nRight, nTop, nBottom;
+
+ nLeft = mrclFrame.Left();
+ nTop = mrclFrame.Top();
+ nRight = mrclFrame.Right();
+ nBottom = mrclFrame.Bottom();
+
+ // emf header info
+ mem << nLeft << nTop << nRight << nBottom;
+ mem << mnPixX << mnPixY << mnMillX << mnMillY;
+
+ float one, zero;
+
+ one = 1;
+ zero = 0;
+
+ // add transformation matrix to be used in vcl's metaact.cxx for
+ // rotate and scale operations
+ mem << one << zero << zero << one << zero << zero;
+
+ // need to flush the stream, otherwise GetEndOfData will return 0
+ // on windows where the function parameters are probably resolved in reverse order
+ mem.Flush();
+
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS_HEADER_INFO", 0, (const sal_uInt8*) mem.GetData(), mem.GetEndOfData() ) );
+ mpGDIMetaFile->UseCanvas( sal_True );
+}
+
+void WinMtfOutput::PassEMFPlus( void* pBuffer, sal_uInt32 nLength )
+{
+ EMFP_DEBUG(printf ("\t\t\tadd EMF_PLUS comment length %04x\n",(unsigned int) nLength));
+ mpGDIMetaFile->AddAction( new MetaCommentAction( "EMF_PLUS", 0, static_cast<const sal_uInt8*>(pBuffer), nLength ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx
new file mode 100644
index 000000000000..bc368e6e6baa
--- /dev/null
+++ b/vcl/source/filter/wmf/winmtf.hxx
@@ -0,0 +1,890 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _WINMTF_HXX
+#define _WINMTF_HXX
+
+#ifdef DBG_UTIL
+#define WIN_MTF_ASSERT
+#endif
+
+#include <sot/object.hxx>
+#include <boost/shared_ptr.hpp>
+#include <vcl/graph.hxx>
+#include <vcl/virdev.hxx>
+#include <basegfx/tools/b2dclipstate.hxx>
+#include <vcl/font.hxx>
+#include <vcl/bmpacc.hxx>
+#include <vcl/lineinfo.hxx>
+#include <svtools/fltcall.hxx>
+
+#define ERROR 0
+#define NULLREGION 1
+#define SIMPLEREGION 2
+#define COMPLEXREGION 3
+
+#define RGN_AND 1
+#define RGN_OR 2
+#define RGN_XOR 3
+#define RGN_DIFF 4
+#define RGN_COPY 5
+
+#define TRANSPARENT 1
+#define OPAQUE 2
+#define BKMODE_LAST 2
+
+/* xform stuff */
+#define MWT_IDENTITY 1
+#define MWT_LEFTMULTIPLY 2
+#define MWT_RIGHTMULTIPLY 3
+
+#define ENHMETA_STOCK_OBJECT 0x80000000
+
+/* Stock Logical Objects */
+#define WHITE_BRUSH 0
+#define LTGRAY_BRUSH 1
+#define GRAY_BRUSH 2
+#define DKGRAY_BRUSH 3
+#define BLACK_BRUSH 4
+#define NULL_BRUSH 5
+#define HOLLOW_BRUSH NULL_BRUSH
+#define WHITE_PEN 6
+#define BLACK_PEN 7
+#define NULL_PEN 8
+#define OEM_FIXED_FONT 10
+#define ANSI_FIXED_FONT 11
+#define ANSI_VAR_FONT 12
+#define SYSTEM_FONT 13
+#define DEVICE_DEFAULT_FONT 14
+#define DEFAULT_PALETTE 15
+#define SYSTEM_FIXED_FONT 16
+
+
+#define R2_BLACK 1
+#define R2_NOTMERGEPEN 2
+#define R2_MASKNOTPEN 3
+#define R2_NOTCOPYPEN 4
+#define R2_MASKPENNOT 5
+#define R2_NOT 6
+#define R2_XORPEN 7
+#define R2_NOTMASKPEN 8
+#define R2_MASKPEN 9
+#define R2_NOTXORPEN 10
+#define R2_NOP 11
+#define R2_MERGENOTPEN 12
+#define R2_COPYPEN 13
+#define R2_MERGEPENNOT 14
+#define R2_MERGEPEN 15
+#define R2_WHITE 16
+
+/* Mapping Modes */
+#define MM_TEXT 1
+#define MM_LOMETRIC 2
+#define MM_HIMETRIC 3
+#define MM_LOENGLISH 4
+#define MM_HIENGLISH 5
+#define MM_TWIPS 6
+#define MM_ISOTROPIC 7
+#define MM_ANISOTROPIC 8
+
+
+/* Graphics Modes */
+#define GM_COMPATIBLE 1
+#define GM_ADVANCED 2
+#define GM_LAST 2
+
+/* StretchBlt() Modes */
+#define BLACKONWHITE 1
+#define WHITEONBLACK 2
+#define COLORONCOLOR 3
+#define HALFTONE 4
+#define MAXSTRETCHBLTMODE 4
+#define STRETCH_ANDSCANS BLACKONWHITE
+#define STRETCH_ORSCANS WHITEONBLACK
+#define STRETCH_DELETESCANS COLORONCOLOR
+#define STRETCH_HALFTONE HALFTONE
+
+#define LF_FACESIZE 32
+
+struct LOGFONTW
+{
+ sal_Int32 lfHeight;
+ sal_Int32 lfWidth;
+ sal_Int32 lfEscapement;
+ sal_Int32 lfOrientation;
+ sal_Int32 lfWeight;
+ sal_uInt8 lfItalic;
+ sal_uInt8 lfUnderline;
+ sal_uInt8 lfStrikeOut;
+ sal_uInt8 lfCharSet;
+ sal_uInt8 lfOutPrecision;
+ sal_uInt8 lfClipPrecision;
+ sal_uInt8 lfQuality;
+ sal_uInt8 lfPitchAndFamily;
+ String alfFaceName;
+};
+struct WMF_EXTERNALHEADER;
+
+#define TA_NOUPDATECP 0x0000
+#define TA_UPDATECP 0x0001
+#define TA_LEFT 0x0000
+#define TA_RIGHT 0x0002
+#define TA_CENTER 0x0006
+#define TA_RIGHT_CENTER (TA_RIGHT | TA_CENTER)
+#define TA_TOP 0x0000
+#define TA_BOTTOM 0x0008
+#define TA_BASELINE 0x0018
+
+#define SRCCOPY 0x00CC0020L
+#define SRCPAINT 0x00EE0086L
+#define SRCAND 0x008800C6L
+#define SRCINVERT 0x00660046L
+#define SRCERASE 0x00440328L
+#define NOTSRCCOPY 0x00330008L
+#define NOTSRCERASE 0x001100A6L
+#define MERGECOPY 0x00C000CAL
+#define MERGEPAINT 0x00BB0226L
+#define PATCOPY 0x00F00021L
+#define PATPAINT 0x00FB0A09L
+#define PATINVERT 0x005A0049L
+#define DSTINVERT 0x00550009L
+#define BLACKNESS 0x00000042L
+#define WHITENESS 0x00FF0062L
+
+#define PS_SOLID 0
+#define PS_DASH 1
+#define PS_DOT 2
+#define PS_DASHDOT 3
+#define PS_DASHDOTDOT 4
+#define PS_NULL 5
+#define PS_INSIDEFRAME 6
+#define PS_USERSTYLE 7
+#define PS_ALTERNATE 8
+#define PS_STYLE_MASK 15
+
+#define PS_ENDCAP_ROUND 0x000
+#define PS_ENDCAP_SQUARE 0x100
+#define PS_ENDCAP_FLAT 0x200
+#define PS_ENDCAP_MASK 0xF00
+
+#define PS_JOIN_ROUND 0x0000
+#define PS_JOIN_BEVEL 0x1000
+#define PS_JOIN_MITER 0x2000
+#define PS_JOIN_MASK 0xF000
+
+#define PS_COSMETIC 0x00000
+#define PS_GEOMETRIC 0x10000
+#define PS_TYPE_MASK 0xF0000
+
+#define ANSI_CHARSET 0
+#define DEFAULT_CHARSET 1
+#define SYMBOL_CHARSET 2
+#define SHIFTJIS_CHARSET 128
+#define HANGEUL_CHARSET 129
+#define GB2312_CHARSET 134
+#define CHINESEBIG5_CHARSET 136
+#define OEM_CHARSET 255
+/*WINVER >= 0x0400*/
+#define JOHAB_CHARSET 130
+#define HEBREW_CHARSET 177
+#define ARABIC_CHARSET 178
+#define GREEK_CHARSET 161
+#define TURKISH_CHARSET 162
+#define VIETNAMESE_CHARSET 163
+#define THAI_CHARSET 222
+#define EASTEUROPE_CHARSET 238
+#define RUSSIAN_CHARSET 204
+#define MAC_CHARSET 77
+#define BALTIC_CHARSET 186
+
+#define ETO_OPAQUE 0x0002
+#define ETO_CLIPPED 0x0004
+/*WINVER >= 0x0400*/
+#define ETO_GLYPH_INDEX 0x0010
+#define ETO_RTLREADING 0x0080
+#define ETO_NUMERICSLOCAL 0x0400
+#define ETO_NUMERICSLATIN 0x0800
+#define ETO_IGNORELANGUAGE 0x1000
+/*_WIN32_WINNT >= 0x0500*/
+#define ETO_PDY 0x2000
+
+
+#define DEFAULT_PITCH 0x00
+#define FIXED_PITCH 0x01
+#define VARIABLE_PITCH 0x02
+
+/* Font Families */
+#define FF_DONTCARE 0x00
+#define FF_ROMAN 0x10
+#define FF_SWISS 0x20
+#define FF_MODERN 0x30
+#define FF_SCRIPT 0x40
+#define FF_DECORATIVE 0x50
+
+#define FW_DONTCARE 0
+#define FW_THIN 100
+#define FW_EXTRALIGHT 200
+#define FW_LIGHT 300
+#define FW_NORMAL 400
+#define FW_MEDIUM 500
+#define FW_SEMIBOLD 600
+#define FW_BOLD 700
+#define FW_EXTRABOLD 800
+#define FW_HEAVY 900
+#define FW_ULTRALIGHT 200
+#define FW_REGULAR 400
+#define FW_DEMIBOLD 600
+#define FW_ULTRABOLD 800
+#define FW_BLACK 900
+
+#define BS_SOLID 0
+#define BS_NULL 1
+#define BS_HOLLOW 1
+#define BS_HATCHED 2
+#define BS_PATTERN 3
+#define BS_INDEXED 4
+#define BS_DIBPATTERN 5
+#define BS_DIBPATTERNPT 6
+#define BS_PATTERN8X8 7
+#define BS_DIBPATTERN8X8 8
+#define BS_MONOPATTERN 9
+
+#define W_HS_HORIZONTAL 0
+#define W_HS_VERTICAL 1
+#define W_HS_FDIAGONAL 2
+#define W_HS_BDIAGONAL 3
+#define W_HS_CROSS 4
+#define W_HS_DIAGCROSS 5
+
+#define RDH_RECTANGLES 1
+
+#define W_MFCOMMENT 15
+
+#define PRIVATE_ESCAPE_UNICODE 2
+
+//============================ WMFReader ==================================
+
+#ifdef WIN_MTF_ASSERT
+#define WIN_MTF_ASSERT_INIT 0x80000000
+#define WIN_MTF_ASSERT_ONCE 0x40000000
+#define WIN_MTF_ASSERT_MIFE 0x20000000
+
+void WinMtfAssertHandler( const sal_Char*, sal_uInt32 nFlags = WIN_MTF_ASSERT_MIFE );
+#endif
+
+class WinMtfClipPath
+{
+ basegfx::tools::B2DClipState maClip;
+
+public :
+ WinMtfClipPath(): maClip() {};
+
+ void setClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode );
+ void intersectClipRect( const Rectangle& rRect );
+ void excludeClipRect( const Rectangle& rRect );
+ void moveClipRegion( const Size& rSize );
+
+ bool isEmpty() const { return maClip.isCleared(); }
+
+ basegfx::B2DPolyPolygon getClipPath() const;
+
+ bool operator==( const WinMtfClipPath& rPath ) const
+ {
+ return maClip == rPath.maClip;
+ };
+};
+
+class WinMtfPathObj : public PolyPolygon
+{
+ sal_Bool bClosed;
+
+public :
+
+ WinMtfPathObj() { bClosed = sal_True; }
+ void Init() { Clear(); bClosed = sal_True; };
+ void ClosePath();
+ void AddPoint( const Point& rPoint );
+ void AddPolygon( const Polygon& rPoly );
+ void AddPolyLine( const Polygon& rPoly );
+ void AddPolyPolygon( const PolyPolygon& rPolyPolygon );
+};
+
+struct WinMtfFontStyle
+{
+ Font aFont;
+
+ WinMtfFontStyle( LOGFONTW& rLogFont );
+};
+
+// -----------------------------------------------------------------------------
+
+typedef enum {
+ FillStyleSolid,
+ FillStylePattern
+} WinMtfFillStyleType;
+
+struct WinMtfFillStyle
+{
+ Color aFillColor;
+ sal_Bool bTransparent;
+ WinMtfFillStyleType aType;
+ Bitmap aBmp;
+
+ WinMtfFillStyle()
+ : aFillColor(Color(COL_BLACK))
+ , bTransparent(sal_False)
+ , aType(FillStyleSolid)
+ {
+ }
+
+ WinMtfFillStyle( const Color& rColor, sal_Bool bTrans = sal_False )
+ : aFillColor(rColor)
+ , bTransparent(bTrans)
+ , aType(FillStyleSolid)
+ {
+ }
+
+ WinMtfFillStyle(Bitmap& rBmp)
+ : aType(FillStylePattern)
+ , aBmp(rBmp)
+ {
+ }
+
+ sal_Bool operator==( const WinMtfFillStyle& rStyle )
+ {
+ return ( ( aFillColor == rStyle.aFillColor )
+ && ( bTransparent == rStyle.bTransparent )
+ && ( aType == rStyle.aType )
+ );
+ }
+ sal_Bool operator==( WinMtfFillStyle* pStyle )
+ {
+ return ( ( aFillColor == pStyle->aFillColor )
+ && ( bTransparent == pStyle->bTransparent )
+ && ( aType == pStyle->aType )
+ );
+ }
+ WinMtfFillStyle& operator=( const WinMtfFillStyle& rStyle )
+ {
+ aFillColor = rStyle.aFillColor;
+ bTransparent = rStyle.bTransparent;
+ aBmp = rStyle.aBmp;
+ aType = rStyle.aType;
+ return *this;
+ }
+ WinMtfFillStyle& operator=( WinMtfFillStyle* pStyle )
+ {
+ aFillColor = pStyle->aFillColor;
+ bTransparent = pStyle->bTransparent;
+ aBmp = pStyle->aBmp;
+ aType = pStyle->aType;
+ return *this;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+struct WinMtfLineStyle
+{
+ Color aLineColor;
+ LineInfo aLineInfo;
+ sal_Bool bTransparent;
+
+ WinMtfLineStyle() :
+ aLineColor ( COL_BLACK ),
+ bTransparent( sal_False ) {}
+
+ WinMtfLineStyle( const Color& rColor, sal_Bool bTrans = sal_False ) :
+ aLineColor ( rColor ),
+ bTransparent( bTrans ) {}
+
+ WinMtfLineStyle( const Color& rColor, const LineInfo& rStyle, sal_Bool bTrans = sal_False ) :
+ aLineColor ( rColor ),
+ aLineInfo ( rStyle ),
+ bTransparent( bTrans ) {}
+
+ sal_Bool operator==( const WinMtfLineStyle& rStyle )
+ {
+ return ( ( aLineColor == rStyle.aLineColor )
+ && ( bTransparent == rStyle.bTransparent )
+ && ( aLineInfo == rStyle.aLineInfo )
+ );
+ }
+ sal_Bool operator==( WinMtfLineStyle* pStyle )
+ {
+ return ( ( aLineColor == pStyle->aLineColor )
+ && ( bTransparent == pStyle->bTransparent )
+ && ( aLineInfo == pStyle->aLineInfo )
+ );
+ }
+ WinMtfLineStyle& operator=( const WinMtfLineStyle& rStyle )
+ {
+ aLineColor = rStyle.aLineColor;
+ bTransparent = rStyle.bTransparent;
+ aLineInfo = rStyle.aLineInfo;
+ return *this;
+ }
+
+ WinMtfLineStyle& operator=( WinMtfLineStyle* pStyle )
+ {
+ aLineColor = pStyle->aLineColor;
+ bTransparent = pStyle->bTransparent;
+ aLineInfo = pStyle->aLineInfo;
+ return *this;
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+struct XForm
+{
+ float eM11;
+ float eM12;
+ float eM21;
+ float eM22;
+ float eDx;
+ float eDy;
+ XForm()
+ {
+ eM11 = eM22 = 1.0f;
+ eDx = eDy = eM12 = eM21 = 0.0f;
+ }
+
+ friend SvStream& operator>>( SvStream& rIn, XForm& rXForm );
+};
+
+// -----------------------------------------------------------------------------
+
+struct SaveStruct
+{
+ sal_uInt32 nBkMode, nMapMode, nGfxMode, nTextLayoutMode;
+ sal_Int32 nWinOrgX, nWinOrgY, nWinExtX, nWinExtY;
+ sal_Int32 nDevOrgX, nDevOrgY, nDevWidth, nDevHeight;
+
+ WinMtfLineStyle aLineStyle;
+ WinMtfFillStyle aFillStyle;
+
+ Font aFont;
+ Color aBkColor;
+ Color aTextColor;
+ sal_uInt32 nTextAlign;
+ RasterOp eRasterOp;
+
+ Point aActPos;
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+ XForm aXForm;
+
+ sal_Bool bRecordPath;
+ sal_Bool bFillStyleSelected;
+};
+
+typedef ::boost::shared_ptr< SaveStruct > SaveStructPtr;
+
+// -----------------------------------------------------------------------------
+
+struct BSaveStruct
+{
+ Bitmap aBmp;
+ Rectangle aOutRect;
+ sal_uInt32 nWinRop;
+ WinMtfFillStyle aStyle;
+
+ BSaveStruct(
+ const Bitmap& rBmp,
+ const Rectangle& rOutRect,
+ sal_uInt32 nRop,
+ WinMtfFillStyle& rStyle
+ )
+ : aBmp( rBmp )
+ , aOutRect( rOutRect )
+ , nWinRop( nRop )
+ , aStyle ( rStyle )
+ {}
+};
+
+typedef ::std::vector< BSaveStruct* > BSaveStructList_impl;
+
+// -----------------------------------------------------------------------------
+
+enum GDIObjectType {
+ GDI_DUMMY = 0,
+ GDI_PEN = 1,
+ GDI_BRUSH = 2,
+ GDI_FONT = 3,
+ GDI_PALETTE = 4,
+ GDI_BITMAP = 5,
+ GDI_REGION = 6
+};
+
+struct GDIObj
+{
+ void* pStyle;
+ GDIObjectType eType;
+
+ GDIObj() :
+ pStyle ( NULL ),
+ eType ( GDI_DUMMY )
+ {
+ }
+
+ GDIObj( GDIObjectType eT, void* pS ) { pStyle = pS; eType = eT; }
+ void Set( GDIObjectType eT, void* pS ) { pStyle = pS; eType = eT; }
+ void Delete()
+ {
+ if ( pStyle )
+ {
+ switch ( eType )
+ {
+ case GDI_PEN :
+ delete (WinMtfLineStyle*)pStyle;
+ break;
+ case GDI_BRUSH :
+ delete (WinMtfFillStyle*)pStyle;
+ break;
+ case GDI_FONT :
+ delete (WinMtfFontStyle*)pStyle;
+ break;
+
+ default:
+ OSL_FAIL( "unsupported style deleted" );
+ break;
+ }
+ pStyle = NULL;
+ }
+ }
+
+ ~GDIObj()
+ {
+ Delete();
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+class WinMtfOutput
+{
+
+ WinMtfPathObj aPathObj;
+ WinMtfClipPath aClipPath;
+
+ WinMtfLineStyle maLatestLineStyle;
+ WinMtfLineStyle maLineStyle;
+ WinMtfFillStyle maLatestFillStyle;
+ WinMtfFillStyle maFillStyle;
+ Font maLatestFont;
+ Font maFont;
+ sal_uInt32 mnLatestTextAlign;
+ sal_uInt32 mnTextAlign;
+ Color maLatestTextColor;
+ Color maTextColor;
+ Color maLatestBkColor;
+ Color maBkColor;
+ sal_uInt32 mnLatestTextLayoutMode;
+ sal_uInt32 mnTextLayoutMode;
+ sal_uInt32 mnLatestBkMode;
+ sal_uInt32 mnBkMode;
+ RasterOp meLatestRasterOp;
+ RasterOp meRasterOp;
+
+ std::vector< GDIObj* > vGDIObj;
+
+ Point maActPos;
+
+ sal_uInt32 mnRop;
+ sal_Bool mbNopMode;
+ sal_Bool mbFillStyleSelected;
+ sal_Bool mbClipNeedsUpdate;
+ sal_Bool mbComplexClip;
+
+ std::vector< SaveStructPtr > vSaveStack;
+
+ sal_uInt32 mnGfxMode;
+ sal_uInt32 mnMapMode;
+ sal_uInt16 mnUnitsPerInch;
+
+ XForm maXForm;
+ sal_Int32 mnDevOrgX, mnDevOrgY;
+ sal_Int32 mnDevWidth, mnDevHeight;
+ sal_Int32 mnWinOrgX, mnWinOrgY; // aktuelles Window-Origin
+ sal_Int32 mnWinExtX, mnWinExtY; // aktuelles Window-Extent
+
+ sal_Int32 mnPixX, mnPixY; // Reference Device in pixel
+ sal_Int32 mnMillX, mnMillY; // Reference Device in Mill
+ Rectangle mrclFrame; // rectangle in logical units 1/100th mm
+ Rectangle mrclBounds;
+
+ GDIMetaFile* mpGDIMetaFile;
+
+ void UpdateLineStyle();
+ void UpdateFillStyle();
+
+ Point ImplMap( const Point& rPt );
+ Size ImplMap( const Size& rSz );
+ Rectangle ImplMap( const Rectangle& rRectangle );
+ void ImplMap( Font& rFont );
+ Polygon& ImplMap( Polygon& rPolygon );
+ PolyPolygon& ImplMap( PolyPolygon& rPolyPolygon );
+ void ImplResizeObjectArry( sal_uInt32 nNewEntry );
+ void ImplSetNonPersistentLineColorTransparenz();
+ void ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly );
+ void ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap );
+
+public:
+
+ void SetDevOrg( const Point& rPoint );
+ void SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd );
+ void SetDevExt( const Size& rSize );
+ void ScaleDevExt( double fX, double fY );
+
+ void SetWinOrg( const Point& rPoint );
+ void SetWinOrgOffset( sal_Int32 nX, sal_Int32 nY );
+ void SetWinExt( const Size& rSize );
+ void ScaleWinExt( double fX, double fY );
+
+ void SetrclBounds( const Rectangle& rRect );
+ void SetrclFrame( const Rectangle& rRect );
+ void SetRefPix( const Size& rSize );
+ void SetRefMill( const Size& rSize );
+
+ sal_uInt32 GetMapMode() const { return mnMapMode; };
+ void SetMapMode( sal_uInt32 mnMapMode );
+ void SetUnitsPerInch( sal_uInt16 nUnitsPerInch );
+ void SetWorldTransform( const XForm& rXForm );
+ void ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode );
+
+ void Push();
+ void Pop();
+
+ sal_uInt32 SetRasterOp( sal_uInt32 nRasterOp );
+ void StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill );
+
+ void SetGfxMode( sal_Int32 nGfxMode ){ mnGfxMode = nGfxMode; };
+ sal_Int32 GetGfxMode() const { return mnGfxMode; };
+ void SetBkMode( sal_uInt32 nMode );
+ void SetBkColor( const Color& rColor );
+ void SetTextColor( const Color& rColor );
+ void SetTextAlign( sal_uInt32 nAlign );
+ void CreateObject( GDIObjectType, void* pStyle = NULL );
+ void CreateObject( sal_Int32 nIndex, GDIObjectType, void* pStyle = NULL );
+ void DeleteObject( sal_Int32 nIndex );
+ void SelectObject( sal_Int32 nIndex );
+ CharSet GetCharSet(){ return maFont.GetCharSet(); };
+ WinMtfFillStyle& GetFillStyle () { return maFillStyle; }
+ const Font& GetFont() const;
+ void SetTextLayoutMode( const sal_uInt32 nLayoutMode );
+
+ void ClearPath(){ aPathObj.Init(); };
+ void ClosePath(){ aPathObj.ClosePath(); };
+ const PolyPolygon& GetPathObj(){ return aPathObj; };
+
+ void MoveTo( const Point& rPoint, sal_Bool bRecordPath = sal_False );
+ void LineTo( const Point& rPoint, sal_Bool bRecordPath = sal_False );
+ void DrawPixel( const Point& rSource, const Color& rColor );
+ void DrawRect( const Rectangle& rRect, sal_Bool bEdge = sal_True );
+ void DrawRoundRect( const Rectangle& rRect, const Size& rSize );
+ void DrawEllipse( const Rectangle& rRect );
+ void DrawArc(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle,
+ sal_Bool bDrawTo = sal_False
+ );
+ void DrawPie(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawChord(
+ const Rectangle& rRect,
+ const Point& rStartAngle,
+ const Point& rEndAngle
+ );
+ void DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath = sal_False );
+ void DrawPolygon( Polygon& rPolygon, sal_Bool /*bDrawTo*/, sal_Bool bRecordPath)
+ {
+ //For ReadAndDrawPolygon template compatibility
+ DrawPolygon(rPolygon, bRecordPath);
+ }
+ void DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath = sal_False );
+ void DrawPolyLine(
+ Polygon& rPolygon,
+ sal_Bool bDrawTo = sal_False,
+ sal_Bool bRecordPath = sal_False
+ );
+ void DrawPolyBezier(
+ Polygon& rPolygin,
+ sal_Bool bDrawTo = sal_False,
+ sal_Bool bRecordPath = sal_False
+ );
+ void DrawText(
+ Point& rPosition,
+ String& rString,
+ sal_Int32* pDXArry = NULL,
+ sal_Bool bRecordPath = sal_False,
+ sal_Int32 nGraphicsMode = GM_COMPATIBLE
+ );
+ void ResolveBitmapActions( BSaveStructList_impl& rSaveList );
+
+ void IntersectClipRect( const Rectangle& rRect );
+ void ExcludeClipRect( const Rectangle& rRect );
+ void MoveClipRegion( const Size& rSize );
+ void SetClipPath(
+ const PolyPolygon& rPolyPoly,
+ sal_Int32 nClippingMode,
+ sal_Bool bIsMapped
+ );
+ void UpdateClipRegion();
+ void AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile );
+
+ void PassEMFPlus( void* pBuffer, sal_uInt32 nLength );
+ void PassEMFPlusHeaderInfo();
+
+ WinMtfOutput( GDIMetaFile& rGDIMetaFile );
+ virtual ~WinMtfOutput();
+};
+
+// -----------------------------------------------------------------------------
+
+class WinMtf
+{
+protected:
+
+ WinMtfOutput* pOut;
+ SvStream* pWMF; // Die einzulesende WMF/EMF-Datei
+
+ sal_uInt32 nStartPos, nEndPos;
+ BSaveStructList_impl aBmpSaveList;
+
+ FilterConfigItem* pFilterConfigItem;
+
+ com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+ // Sorgt dafuer, das aSampledBrush der aktuelle Brush des GDIMetaFiles ist.
+
+ Color ReadColor();
+ void Callback( sal_uInt16 nPercent );
+
+ WinMtf(
+ WinMtfOutput* pOut,
+ SvStream& rStreamWMF,
+ FilterConfigItem* pConfigItem = NULL
+ );
+ ~WinMtf();
+};
+
+//============================ EMFReader ==================================
+
+class EnhWMFReader : public WinMtf
+{
+ sal_Bool bRecordPath;
+ sal_Int32 nRecordCount;
+ sal_Bool bEMFPlus;
+
+
+ sal_Bool ReadHeader();
+ // Liesst und konvertiert ein Rechteck
+ Rectangle ReadRectangle( sal_Int32, sal_Int32, sal_Int32, sal_Int32 );
+ void ImplExtTextOut( sal_Bool bWideCharakter );
+
+public:
+ EnhWMFReader(
+ SvStream& rStreamWMF,
+ GDIMetaFile& rGDIMetaFile,
+ FilterConfigItem* pConfigItem = NULL
+ )
+ : WinMtf( new WinMtfOutput( rGDIMetaFile )
+ , rStreamWMF
+ , pConfigItem )
+ , bRecordPath( sal_False )
+ , bEMFPlus( sal_False )
+ {};
+ ~EnhWMFReader();
+
+ sal_Bool ReadEnhWMF();
+ void ReadEMFPlusComment(sal_uInt32 length, sal_Bool& bHaveDC);
+private:
+ template <class T> void ReadAndDrawPolyPolygon();
+ template <class T> void ReadAndDrawPolyLine();
+ template <class T> Polygon ReadPolygon(sal_uInt32 nStartIndex, sal_uInt32 nPoints);
+ template <class T, class Drawer> void ReadAndDrawPolygon(Drawer drawer, const sal_Bool skipFirst);
+};
+
+//============================ WMFReader ==================================
+
+class WMFReader : public WinMtf
+{
+private:
+
+ VirtualDevice aVDev; // just for the purpose of "IsFontAvailable"
+ sal_uInt16 nUnitsPerInch;
+ sal_uInt32 nRecSize;
+
+ // embedded EMF data
+ SvMemoryStream* pEMFStream;
+
+ // total number of comment records containing EMF data
+ sal_uInt32 nEMFRecCount;
+
+ // number of EMF records read
+ sal_uInt32 nEMFRec;
+
+ // total size of embedded EMF data
+ sal_uInt32 nEMFSize;
+
+ sal_uInt32 nSkipActions;
+ sal_uInt32 nCurrentAction;
+ sal_uInt32 nUnicodeEscapeAction;
+
+ WMF_EXTERNALHEADER* pExternalHeader;
+
+ // Liesst den Kopf der WMF-Datei
+ sal_Bool ReadHeader();
+
+ // Liesst die Parameter des Rocords mit der Funktionsnummer nFunction.
+ void ReadRecordParams( sal_uInt16 nFunction );
+
+ Point ReadPoint(); // Liesst und konvertiert einen Punkt (erst X dann Y)
+ Point ReadYX(); // Liesst und konvertiert einen Punkt (erst Y dann X)
+ Rectangle ReadRectangle(); // Liesst und konvertiert ein Rechteck
+ Size ReadYXExt();
+ sal_Bool GetPlaceableBound( Rectangle& rSize, SvStream* pStrm );
+
+public:
+
+ WMFReader(
+ SvStream& rStreamWMF,
+ GDIMetaFile& rGDIMetaFile,
+ FilterConfigItem* pConfigItem = NULL,
+ WMF_EXTERNALHEADER* pExtHeader = NULL
+ )
+ : WinMtf( new WinMtfOutput( rGDIMetaFile ), rStreamWMF, pConfigItem )
+ , pEMFStream(NULL),
+ pExternalHeader(pExtHeader)
+ {}
+
+ ~WMFReader();
+
+ // Liesst aus dem Stream eine WMF-Datei und fuellt das GDIMetaFile
+ void ReadWMF();
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx
new file mode 100644
index 000000000000..f9f38e09eb92
--- /dev/null
+++ b/vcl/source/filter/wmf/winwmf.cxx
@@ -0,0 +1,1503 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "winmtf.hxx"
+#include <boost/scoped_array.hpp>
+#include <vcl/gdimtf.hxx>
+#include <svtools/wmf.hxx>
+#include <rtl/crc.h>
+#include <rtl/tencinfo.h>
+#include <osl/endian.h>
+
+//====================== MS-Windows-defines ===============================
+
+#define W_META_SETBKCOLOR 0x0201
+#define W_META_SETBKMODE 0x0102
+#define W_META_SETMAPMODE 0x0103
+#define W_META_SETROP2 0x0104
+#define W_META_SETRELABS 0x0105
+#define W_META_SETPOLYFILLMODE 0x0106
+#define W_META_SETSTRETCHBLTMODE 0x0107
+#define W_META_SETTEXTCHAREXTRA 0x0108
+#define W_META_SETTEXTCOLOR 0x0209
+#define W_META_SETTEXTJUSTIFICATION 0x020A
+#define W_META_SETWINDOWORG 0x020B
+#define W_META_SETWINDOWEXT 0x020C
+#define W_META_SETVIEWPORTORG 0x020D
+#define W_META_SETVIEWPORTEXT 0x020E
+#define W_META_OFFSETWINDOWORG 0x020F
+#define W_META_SCALEWINDOWEXT 0x0410
+#define W_META_OFFSETVIEWPORTORG 0x0211
+#define W_META_SCALEVIEWPORTEXT 0x0412
+#define W_META_LINETO 0x0213
+#define W_META_MOVETO 0x0214
+#define W_META_EXCLUDECLIPRECT 0x0415
+#define W_META_INTERSECTCLIPRECT 0x0416
+#define W_META_ARC 0x0817
+#define W_META_ELLIPSE 0x0418
+#define W_META_FLOODFILL 0x0419
+#define W_META_PIE 0x081A
+#define W_META_RECTANGLE 0x041B
+#define W_META_ROUNDRECT 0x061C
+#define W_META_PATBLT 0x061D
+#define W_META_SAVEDC 0x001E
+#define W_META_SETPIXEL 0x041F
+#define W_META_OFFSETCLIPRGN 0x0220
+#define W_META_TEXTOUT 0x0521
+#define W_META_BITBLT 0x0922
+#define W_META_STRETCHBLT 0x0B23
+#define W_META_POLYGON 0x0324
+#define W_META_POLYLINE 0x0325
+#define W_META_ESCAPE 0x0626
+#define W_META_RESTOREDC 0x0127
+#define W_META_FILLREGION 0x0228
+#define W_META_FRAMEREGION 0x0429
+#define W_META_INVERTREGION 0x012A
+#define W_META_PAINTREGION 0x012B
+#define W_META_SELECTCLIPREGION 0x012C
+#define W_META_SELECTOBJECT 0x012D
+#define W_META_SETTEXTALIGN 0x012E
+#define W_META_DRAWTEXT 0x062F
+#define W_META_CHORD 0x0830
+#define W_META_SETMAPPERFLAGS 0x0231
+#define W_META_EXTTEXTOUT 0x0a32
+#define W_META_SETDIBTODEV 0x0d33
+#define W_META_SELECTPALETTE 0x0234
+#define W_META_REALIZEPALETTE 0x0035
+#define W_META_ANIMATEPALETTE 0x0436
+#define W_META_SETPALENTRIES 0x0037
+#define W_META_POLYPOLYGON 0x0538
+#define W_META_RESIZEPALETTE 0x0139
+#define W_META_DIBBITBLT 0x0940
+#define W_META_DIBSTRETCHBLT 0x0b41
+#define W_META_DIBCREATEPATTERNBRUSH 0x0142
+#define W_META_STRETCHDIB 0x0f43
+#define W_META_EXTFLOODFILL 0x0548
+#define W_META_RESETDC 0x014C
+#define W_META_STARTDOC 0x014D
+#define W_META_STARTPAGE 0x004F
+#define W_META_ENDPAGE 0x0050
+#define W_META_ABORTDOC 0x0052
+#define W_META_ENDDOC 0x005E
+#define W_META_DELETEOBJECT 0x01f0
+#define W_META_CREATEPALETTE 0x00f7
+#define W_META_CREATEBRUSH 0x00F8
+#define W_META_CREATEPATTERNBRUSH 0x01F9
+#define W_META_CREATEPENINDIRECT 0x02FA
+#define W_META_CREATEFONTINDIRECT 0x02FB
+#define W_META_CREATEBRUSHINDIRECT 0x02FC
+#define W_META_CREATEBITMAPINDIRECT 0x02FD
+#define W_META_CREATEBITMAP 0x06FE
+#define W_META_CREATEREGION 0x06FF
+
+static void GetWinExtMax( const Point& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
+{
+ Point aSource( rSource );
+ if ( nMapMode == MM_HIMETRIC )
+ aSource.Y() = -rSource.Y();
+ if ( aSource.X() < rPlaceableBound.Left() )
+ rPlaceableBound.Left() = aSource.X();
+ if ( aSource.X() > rPlaceableBound.Right() )
+ rPlaceableBound.Right() = aSource.X();
+ if ( aSource.Y() < rPlaceableBound.Top() )
+ rPlaceableBound.Top() = aSource.Y();
+ if ( aSource.Y() > rPlaceableBound.Bottom() )
+ rPlaceableBound.Bottom() = aSource.Y();
+}
+
+static void GetWinExtMax( const Rectangle& rSource, Rectangle& rPlaceableBound, const sal_Int16 nMapMode )
+{
+ GetWinExtMax( rSource.TopLeft(), rPlaceableBound, nMapMode );
+ GetWinExtMax( rSource.BottomRight(), rPlaceableBound, nMapMode );
+}
+
+//=================== Methods of WMFReader ==============================
+
+inline Point WMFReader::ReadPoint()
+{
+ short nX = 0, nY = 0;
+ *pWMF >> nX >> nY;
+ return Point( nX, nY );
+}
+
+// ------------------------------------------------------------------------
+
+inline Point WMFReader::ReadYX()
+{
+ short nX = 0, nY = 0;
+ *pWMF >> nY >> nX;
+ return Point( nX, nY );
+}
+
+// ------------------------------------------------------------------------
+
+Rectangle WMFReader::ReadRectangle()
+{
+ Point aBR, aTL;
+ aBR = ReadYX();
+ aTL = ReadYX();
+ aBR.X()--;
+ aBR.Y()--;
+ return Rectangle( aTL, aBR );
+}
+
+// ------------------------------------------------------------------------
+
+Size WMFReader::ReadYXExt()
+{
+ short nW=0, nH=0;
+ *pWMF >> nH >> nW;
+ return Size( nW, nH );
+}
+
+// ------------------------------------------------------------------------
+
+void WMFReader::ReadRecordParams( sal_uInt16 nFunc )
+{
+ switch( nFunc )
+ {
+ case W_META_SETBKCOLOR:
+ {
+ pOut->SetBkColor( ReadColor() );
+ }
+ break;
+
+ case W_META_SETBKMODE:
+ {
+ sal_uInt16 nDat = 0;
+ *pWMF >> nDat;
+ pOut->SetBkMode( nDat );
+ }
+ break;
+
+ // !!!
+ case W_META_SETMAPMODE:
+ {
+ sal_Int16 nMapMode = 0;
+ *pWMF >> nMapMode;
+ pOut->SetMapMode( nMapMode );
+ }
+ break;
+
+ case W_META_SETROP2:
+ {
+ sal_uInt16 nROP2 = 0;
+ *pWMF >> nROP2;
+ pOut->SetRasterOp( nROP2 );
+ }
+ break;
+
+ case W_META_SETTEXTCOLOR:
+ {
+ pOut->SetTextColor( ReadColor() );
+ }
+ break;
+
+ case W_META_SETWINDOWORG:
+ {
+ pOut->SetWinOrg( ReadYX() );
+ }
+ break;
+
+ case W_META_SETWINDOWEXT:
+ {
+ short nWidth = 0, nHeight = 0;
+ *pWMF >> nHeight >> nWidth;
+ pOut->SetWinExt( Size( nWidth, nHeight ) );
+ }
+ break;
+
+ case W_META_OFFSETWINDOWORG:
+ {
+ short nXAdd = 0, nYAdd = 0;
+ *pWMF >> nYAdd >> nXAdd;
+ pOut->SetWinOrgOffset( nXAdd, nYAdd );
+ }
+ break;
+
+ case W_META_SCALEWINDOWEXT:
+ {
+ short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
+ *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
+ pOut->ScaleWinExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
+ }
+ break;
+
+ case W_META_SETVIEWPORTORG:
+ case W_META_SETVIEWPORTEXT:
+ break;
+
+ case W_META_OFFSETVIEWPORTORG:
+ {
+ short nXAdd = 0, nYAdd = 0;
+ *pWMF >> nYAdd >> nXAdd;
+ pOut->SetDevOrgOffset( nXAdd, nYAdd );
+ }
+ break;
+
+ case W_META_SCALEVIEWPORTEXT:
+ {
+ short nXNum = 0, nXDenom = 0, nYNum = 0, nYDenom = 0;
+ *pWMF >> nYDenom >> nYNum >> nXDenom >> nXNum;
+ pOut->ScaleDevExt( (double)nXNum / nXDenom, (double)nYNum / nYDenom );
+ }
+ break;
+
+ case W_META_LINETO:
+ {
+ pOut->LineTo( ReadYX() );
+ }
+ break;
+
+ case W_META_MOVETO:
+ {
+ pOut->MoveTo( ReadYX() );
+ }
+ break;
+
+ case W_META_INTERSECTCLIPRECT:
+ {
+ pOut->IntersectClipRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_RECTANGLE:
+ {
+ pOut->DrawRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_ROUNDRECT:
+ {
+ Size aSize( ReadYXExt() );
+ pOut->DrawRoundRect( ReadRectangle(), Size( aSize.Width() / 2, aSize.Height() / 2 ) );
+ }
+ break;
+
+ case W_META_ELLIPSE:
+ {
+ pOut->DrawEllipse( ReadRectangle() );
+ }
+ break;
+
+ case W_META_ARC:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+ pOut->DrawArc( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_PIE:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+
+ // #i73608# OutputDevice deviates from WMF
+ // semantics. start==end means full ellipse here.
+ if( aStart == aEnd )
+ pOut->DrawEllipse( aRect );
+ else
+ pOut->DrawPie( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_CHORD:
+ {
+ Point aEnd( ReadYX() );
+ Point aStart( ReadYX() );
+ Rectangle aRect( ReadRectangle() );
+ aRect.Justify();
+ pOut->DrawChord( aRect, aStart, aEnd );
+ }
+ break;
+
+ case W_META_POLYGON:
+ {
+ sal_uInt16 nPoints = 0;
+ *pWMF >> nPoints;
+ Polygon aPoly( nPoints );
+ for( sal_uInt16 i = 0; i < nPoints; i++ )
+ aPoly[ i ] = ReadPoint();
+ pOut->DrawPolygon( aPoly );
+ }
+ break;
+
+ case W_META_POLYPOLYGON:
+ {
+ bool bRecordOk = true;
+ sal_uInt16 nPoly = 0;
+ Point* pPtAry;
+ // Number of polygons:
+ *pWMF >> nPoly;
+ // Number of points of each polygon. Determine total number of points
+ boost::scoped_array<sal_uInt16> xPolygonPointCounts(new sal_uInt16[nPoly]);
+ sal_uInt16* pnPoints = xPolygonPointCounts.get();
+ sal_uInt16 nPoints = 0;
+ for(sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ *pWMF >> pnPoints[i];
+
+ if (pnPoints[i] > SAL_MAX_UINT16 - nPoints)
+ {
+ bRecordOk = false;
+ break;
+ }
+
+ nPoints += pnPoints[i];
+ }
+
+ SAL_WARN_IF(!bRecordOk, "svtools.filter", "polypolygon record has more polygons than we can handle");
+
+ bRecordOk &= pWMF->good();
+
+ if (!bRecordOk)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+
+ // Polygon points are:
+ boost::scoped_array<Point> xPolygonPoints(new Point[nPoints]);
+ pPtAry = xPolygonPoints.get();
+ for (sal_uInt16 i = 0; i < nPoints; i++ )
+ pPtAry[ i ] = ReadPoint();
+
+ bRecordOk &= pWMF->good();
+
+ if (!bRecordOk)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+
+ // Produce PolyPolygon Actions
+ PolyPolygon aPolyPoly( nPoly, pnPoints, pPtAry );
+ pOut->DrawPolyPolygon( aPolyPoly );
+ }
+ break;
+
+ case W_META_POLYLINE:
+ {
+ sal_uInt16 nPoints = 0;
+ *pWMF >> nPoints;
+ Polygon aPoly( nPoints );
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ aPoly[ i ] = ReadPoint();
+ pOut->DrawPolyLine( aPoly );
+ }
+ break;
+
+ case W_META_SAVEDC:
+ {
+ pOut->Push();
+ }
+ break;
+
+ case W_META_RESTOREDC:
+ {
+ pOut->Pop();
+ }
+ break;
+
+ case W_META_SETPIXEL:
+ {
+ const Color aColor = ReadColor();
+ pOut->DrawPixel( ReadYX(), aColor );
+ }
+ break;
+
+ case W_META_OFFSETCLIPRGN:
+ {
+ pOut->MoveClipRegion( ReadYXExt() );
+ }
+ break;
+
+ case W_META_TEXTOUT:
+ {
+ sal_uInt16 nLength = 0;
+ *pWMF >> nLength;
+ if ( nLength )
+ {
+ char* pChar = new char[ ( nLength + 1 ) &~ 1 ];
+ pWMF->Read( pChar, ( nLength + 1 ) &~ 1 );
+ String aText( pChar, nLength, pOut->GetCharSet() );
+ delete[] pChar;
+ Point aPosition( ReadYX() );
+ pOut->DrawText( aPosition, aText );
+ }
+ }
+ break;
+
+ case W_META_EXTTEXTOUT:
+ {
+ sal_uInt16 nLen = 0, nOptions = 0;
+ sal_Int32 nRecordPos, nRecordSize = 0, nOriginalTextLen, nNewTextLen;
+ Point aPosition;
+ Rectangle aRect;
+ sal_Int32* pDXAry = NULL;
+
+ pWMF->SeekRel(-6);
+ nRecordPos = pWMF->Tell();
+ *pWMF >> nRecordSize;
+ pWMF->SeekRel(2);
+ aPosition = ReadYX();
+ *pWMF >> nLen >> nOptions;
+
+ sal_Int32 nTextLayoutMode = TEXT_LAYOUT_DEFAULT;
+ if ( nOptions & ETO_RTLREADING )
+ nTextLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_TEXTORIGIN_LEFT;
+ pOut->SetTextLayoutMode( nTextLayoutMode );
+ DBG_ASSERT( ( nOptions & ( ETO_PDY | ETO_GLYPH_INDEX ) ) == 0, "SJ: ETO_PDY || ETO_GLYPH_INDEX in WMF" );
+
+ // Nur wenn der Text auch Zeichen enthaelt, macht die Ausgabe Sinn
+ if( nLen )
+ {
+ nOriginalTextLen = nLen;
+ if( nOptions & ETO_CLIPPED )
+ {
+ const Point aPt1( ReadPoint() );
+ const Point aPt2( ReadPoint() );
+ aRect = Rectangle( aPt1, aPt2 );
+ }
+ char* pChar = new char[ ( nOriginalTextLen + 1 ) &~ 1 ];
+ pWMF->Read( pChar, ( nOriginalTextLen + 1 ) &~ 1 );
+ String aText( pChar, (sal_uInt16)nOriginalTextLen, pOut->GetCharSet() );// after this conversion the text may contain
+ nNewTextLen = aText.Len(); // less character (japanese version), so the
+ delete[] pChar; // dxAry will not fit
+
+ if ( nNewTextLen )
+ {
+ sal_uInt32 nMaxStreamPos = nRecordPos + ( nRecordSize << 1 );
+ sal_Int32 nDxArySize = nMaxStreamPos - pWMF->Tell();
+ sal_Int32 nDxAryEntries = nDxArySize >> 1;
+ sal_Bool bUseDXAry = sal_False;
+
+ if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
+ {
+ sal_Int16 nDx = 0, nDxTmp = 0;
+ sal_uInt16 i; //needed just outside the for
+ pDXAry = new sal_Int32[ nNewTextLen ];
+ for (i = 0; i < nNewTextLen; i++ )
+ {
+ if ( pWMF->Tell() >= nMaxStreamPos )
+ break;
+ *pWMF >> nDx;
+ if ( nNewTextLen != nOriginalTextLen )
+ {
+ sal_Unicode nUniChar = aText.GetChar(i);
+ rtl::OString aTmp(&nUniChar, 1, pOut->GetCharSet());
+ if ( aTmp.getLength() > 1 )
+ {
+ sal_Int32 nDxCount = aTmp.getLength() - 1;
+ if ( ( ( nDxCount * 2 ) + pWMF->Tell() ) > nMaxStreamPos )
+ break;
+ while ( nDxCount-- )
+ {
+ *pWMF >> nDxTmp;
+ nDx = nDx + nDxTmp;
+ }
+ }
+ }
+ pDXAry[ i ] = nDx;
+ }
+ if ( i == nNewTextLen )
+ bUseDXAry = sal_True;
+ }
+ if ( pDXAry && bUseDXAry )
+ pOut->DrawText( aPosition, aText, pDXAry );
+ else
+ pOut->DrawText( aPosition, aText );
+ }
+ }
+ delete[] pDXAry;
+
+ }
+ break;
+
+ case W_META_SELECTOBJECT:
+ {
+ sal_Int16 nObjIndex = 0;
+ *pWMF >> nObjIndex;
+ pOut->SelectObject( nObjIndex );
+ }
+ break;
+
+ case W_META_SETTEXTALIGN:
+ {
+ sal_uInt16 nAlign = 0;
+ *pWMF >> nAlign;
+ pOut->SetTextAlign( nAlign );
+ }
+ break;
+
+ case W_META_BITBLT:
+ {
+ // 0-3 : nWinROP #93454#
+ // 4-5 : y offset of source bitmap
+ // 6-7 : x offset of source bitmap
+ // 8-9 : used height of source bitmap
+ // 10-11 : used width of source bitmap
+ // 12-13 : destination position y (in pixel)
+ // 14-15 : destination position x (in pixel)
+ // 16-17 : dont know
+ // 18-19 : Width Bitmap in Pixel
+ // 20-21 : Height Bitmap in Pixel
+ // 22-23 : bytes per scanline
+ // 24 : planes
+ // 25 : bitcount
+
+ sal_Int32 nWinROP = 0;
+ sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nDontKnow = 0, nWidth = 0, nHeight = 0, nBytesPerScan = 0;
+ sal_uInt8 nPlanes, nBitCount;
+
+ *pWMF >> nWinROP
+ >> nSy >> nSx >> nSye >> nSxe;
+ Point aPoint( ReadYX() );
+ *pWMF >> nDontKnow >> nWidth >> nHeight >> nBytesPerScan >> nPlanes >> nBitCount;
+
+ if ( nWidth && nHeight && ( nPlanes == 1 ) && ( nBitCount == 1 ) )
+ {
+ Bitmap aBmp( Size( nWidth, nHeight ), nBitCount );
+ BitmapWriteAccess* pAcc;
+ pAcc = aBmp.AcquireWriteAccess();
+ if ( pAcc )
+ {
+ for (sal_uInt16 y = 0; y < nHeight; y++ )
+ {
+ sal_uInt16 x = 0;
+ for (sal_uInt16 scan = 0; scan < nBytesPerScan; scan++ )
+ {
+ sal_Int8 nEightPixels = 0;
+ *pWMF >> nEightPixels;
+ for (sal_Int8 i = 7; i >= 0; i-- )
+ {
+ if ( x < nWidth )
+ {
+ pAcc->SetPixel( y, x, (nEightPixels>>i)&1 );
+ }
+ x++;
+ }
+ }
+ }
+ aBmp.ReleaseAccess( pAcc );
+ if ( nSye && nSxe &&
+ ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
+ ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
+ {
+ Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ aBmp.Crop( aCropRect );
+ }
+ Rectangle aDestRect( aPoint, Size( nSxe, nSye ) );
+ aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case W_META_STRETCHBLT:
+ case W_META_DIBBITBLT:
+ case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHDIB:
+ {
+ sal_Int32 nWinROP = 0;
+ sal_uInt16 nSx = 0, nSy = 0, nSxe = 0, nSye = 0, nUsage = 0;
+ Bitmap aBmp;
+
+ *pWMF >> nWinROP;
+
+ if( nFunc == W_META_STRETCHDIB )
+ *pWMF >> nUsage;
+
+ // nSye and nSxe is the number of pixels that has to been used
+ // If they are set to zero, it is as indicator not to scale the bitmap later
+ //
+ if( nFunc == W_META_STRETCHDIB || nFunc == W_META_STRETCHBLT || nFunc == W_META_DIBSTRETCHBLT )
+ *pWMF >> nSye >> nSxe;
+
+ // nSy and nx is the offset of the first pixel
+ *pWMF >> nSy >> nSx;
+
+ if( nFunc == W_META_STRETCHDIB || nFunc == W_META_DIBBITBLT || nFunc == W_META_DIBSTRETCHBLT )
+ {
+ if ( nWinROP == PATCOPY )
+ *pWMF >> nUsage; // i don't know anything of this parameter, so its called nUsage
+ // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
+
+ Size aDestSize( ReadYXExt() );
+ if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
+ {
+ Rectangle aDestRect( ReadYX(), aDestSize );
+ if ( nWinROP != PATCOPY )
+ aBmp.Read( *pWMF, sal_False );
+
+ // test if it is sensible to crop
+ if ( nSye && nSxe &&
+ ( ( nSx + nSxe ) <= aBmp.GetSizePixel().Width() ) &&
+ ( ( nSy + nSye <= aBmp.GetSizePixel().Height() ) ) )
+ {
+ Rectangle aCropRect( Point( nSx, nSy ), Size( nSxe, nSye ) );
+ aBmp.Crop( aCropRect );
+ }
+ aBmpSaveList.push_back( new BSaveStruct( aBmp, aDestRect, nWinROP, pOut->GetFillStyle () ) );
+ }
+ }
+ }
+ break;
+
+ case W_META_DIBCREATEPATTERNBRUSH:
+ {
+ Bitmap aBmp;
+ BitmapReadAccess* pBmp;
+ sal_uInt32 nRed = 0, nGreen = 0, nBlue = 0, nCount = 1;
+ sal_uInt16 nFunction = 0;
+
+ *pWMF >> nFunction >> nFunction;
+
+ aBmp.Read( *pWMF, sal_False );
+ pBmp = aBmp.AcquireReadAccess();
+ if ( pBmp )
+ {
+ for ( sal_Int32 y = 0; y < pBmp->Height(); y++ )
+ {
+ for ( sal_Int32 x = 0; x < pBmp->Width(); x++ )
+ {
+ const BitmapColor aColor( pBmp->GetColor( y, x ) );
+
+ nRed += aColor.GetRed();
+ nGreen += aColor.GetGreen();
+ nBlue += aColor.GetBlue();
+ }
+ }
+ nCount = pBmp->Height() * pBmp->Width();
+ if ( !nCount )
+ nCount++;
+ aBmp.ReleaseAccess( pBmp );
+ }
+ Color aColor( (sal_uInt8)( nRed / nCount ), (sal_uInt8)( nGreen / nCount ), (sal_uInt8)( nBlue / nCount ) );
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( aColor, sal_False ) );
+ }
+ break;
+
+ case W_META_DELETEOBJECT:
+ {
+ sal_Int16 nIndex = 0;
+ *pWMF >> nIndex;
+ pOut->DeleteObject( nIndex );
+ }
+ break;
+
+ case W_META_CREATEPALETTE:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEBRUSH:
+ {
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEPATTERNBRUSH:
+ {
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ), sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEPENINDIRECT:
+ {
+ LineInfo aLineInfo;
+ sal_uInt16 nStyle = 0, nWidth = 0, nHeight = 0;
+
+ *pWMF >> nStyle >> nWidth >> nHeight;
+
+ if ( nWidth )
+ aLineInfo.SetWidth( nWidth );
+
+ sal_Bool bTransparent = sal_False;
+ sal_uInt16 nDashCount = 0;
+ sal_uInt16 nDotCount = 0;
+ switch( nStyle )
+ {
+ case PS_DASHDOTDOT :
+ nDotCount++;
+ case PS_DASHDOT :
+ nDashCount++;
+ case PS_DOT :
+ nDotCount++;
+ break;
+ case PS_DASH :
+ nDashCount++;
+ break;
+ case PS_NULL :
+ bTransparent = sal_True;
+ aLineInfo.SetStyle( LINE_NONE );
+ break;
+ default :
+ case PS_INSIDEFRAME :
+ case PS_SOLID :
+ aLineInfo.SetStyle( LINE_SOLID );
+ }
+ if ( nDashCount | nDotCount )
+ {
+ aLineInfo.SetStyle( LINE_DASH );
+ aLineInfo.SetDashCount( nDashCount );
+ aLineInfo.SetDotCount( nDotCount );
+ }
+ pOut->CreateObject( GDI_PEN, new WinMtfLineStyle( ReadColor(), aLineInfo, bTransparent ) );
+ }
+ break;
+
+ case W_META_CREATEBRUSHINDIRECT:
+ {
+ sal_uInt16 nStyle = 0;
+ *pWMF >> nStyle;
+ pOut->CreateObject( GDI_BRUSH, new WinMtfFillStyle( ReadColor(), ( nStyle == BS_HOLLOW ) ? sal_True : sal_False ) );
+ }
+ break;
+
+ case W_META_CREATEFONTINDIRECT:
+ {
+ Size aFontSize;
+ char lfFaceName[ LF_FACESIZE ];
+ sal_Int16 lfEscapement = 0, lfOrientation = 0, lfWeight = 0; // ( formerly sal_uInt16 )
+
+ LOGFONTW aLogFont;
+ aFontSize = ReadYXExt();
+ *pWMF >> lfEscapement >> lfOrientation >> lfWeight
+ >> aLogFont.lfItalic >> aLogFont.lfUnderline >> aLogFont.lfStrikeOut >> aLogFont.lfCharSet >> aLogFont.lfOutPrecision
+ >> aLogFont.lfClipPrecision >> aLogFont.lfQuality >> aLogFont.lfPitchAndFamily;
+ pWMF->Read( lfFaceName, LF_FACESIZE );
+ aLogFont.lfWidth = aFontSize.Width();
+ aLogFont.lfHeight = aFontSize.Height();
+ aLogFont.lfEscapement = lfEscapement;
+ aLogFont.lfOrientation = lfOrientation;
+ aLogFont.lfWeight = lfWeight;
+
+ CharSet eCharSet;
+ if ( ( aLogFont.lfCharSet == OEM_CHARSET ) || ( aLogFont.lfCharSet == DEFAULT_CHARSET ) )
+ eCharSet = osl_getThreadTextEncoding();
+ else
+ eCharSet = rtl_getTextEncodingFromWindowsCharset( aLogFont.lfCharSet );
+ if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
+ eCharSet = osl_getThreadTextEncoding();
+ if ( eCharSet == RTL_TEXTENCODING_SYMBOL )
+ eCharSet = RTL_TEXTENCODING_MS_1252;
+ aLogFont.alfFaceName = UniString( lfFaceName, eCharSet );
+
+ pOut->CreateObject( GDI_FONT, new WinMtfFontStyle( aLogFont ) );
+ }
+ break;
+
+ case W_META_CREATEBITMAPINDIRECT:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEBITMAP:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_CREATEREGION:
+ {
+ pOut->CreateObject( GDI_DUMMY );
+ }
+ break;
+
+ case W_META_EXCLUDECLIPRECT :
+ {
+ pOut->ExcludeClipRect( ReadRectangle() );
+ }
+ break;
+
+ case W_META_PATBLT:
+ {
+ sal_uInt32 nROP = 0, nOldROP = 0;
+ *pWMF >> nROP;
+ Size aSize = ReadYXExt();
+ nOldROP = pOut->SetRasterOp( nROP );
+ pOut->DrawRect( Rectangle( ReadYX(), aSize ), sal_False );
+ pOut->SetRasterOp( nOldROP );
+ }
+ break;
+
+ case W_META_SELECTCLIPREGION:
+ {
+ sal_Int16 nObjIndex = 0;
+ *pWMF >> nObjIndex;
+ if ( !nObjIndex )
+ {
+ PolyPolygon aEmptyPolyPoly;
+ pOut->SetClipPath( aEmptyPolyPoly, RGN_COPY, sal_True );
+ }
+ }
+ break;
+
+ case W_META_ESCAPE :
+ {
+ // nRecSize has been checked previously to be greater than 3
+ sal_uInt64 nMetaRecSize = static_cast< sal_uInt64 >( nRecSize - 2 ) * 2;
+ sal_uInt64 nMetaRecEndPos = pWMF->Tell() + nMetaRecSize;
+
+ // taking care that nRecSize does not exceed the maximal stream position
+ if ( nMetaRecEndPos > nEndPos )
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+ if ( nRecSize >= 4 ) // minimal escape lenght
+ {
+ sal_uInt16 nMode = 0, nLen = 0;
+ *pWMF >> nMode
+ >> nLen;
+ if ( ( nMode == W_MFCOMMENT ) && ( nLen >= 4 ) )
+ {
+ sal_uInt32 nNewMagic = 0; // we have to read int32 for
+ *pWMF >> nNewMagic; // META_ESCAPE_ENHANCED_METAFILE CommentIdentifier
+
+ if( nNewMagic == 0x2c2a4f4f && nLen >= 14 )
+ {
+ sal_uInt16 nMagic2 = 0;
+ *pWMF >> nMagic2;
+ if( nMagic2 == 0x0a ) // 2nd half of magic
+ { // continue with private escape
+ sal_uInt32 nCheck = 0, nEsc = 0;
+ *pWMF >> nCheck
+ >> nEsc;
+
+ sal_uInt32 nEscLen = nLen - 14;
+ if ( nEscLen <= ( nRecSize * 2 ) )
+ {
+#ifdef OSL_BIGENDIAN
+ sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
+#else
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
+#endif
+ sal_Int8* pData = NULL;
+
+ if ( ( static_cast< sal_uInt64 >( nEscLen ) + pWMF->Tell() ) > nMetaRecEndPos )
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ break;
+ }
+ if ( nEscLen > 0 )
+ {
+ pData = new sal_Int8[ nEscLen ];
+ pWMF->Read( pData, nEscLen );
+ nCheckSum = rtl_crc32( nCheckSum, pData, nEscLen );
+ }
+ if ( nCheck == nCheckSum )
+ {
+ switch( nEsc )
+ {
+ case PRIVATE_ESCAPE_UNICODE :
+ { // we will use text instead of polygons only if we have the correct font
+ if ( aVDev.IsFontAvailable( pOut->GetFont().GetName() ) )
+ {
+ Point aPt;
+ String aString;
+ sal_uInt32 nStringLen, nDXCount;
+ sal_Int32* pDXAry = NULL;
+ SvMemoryStream aMemoryStream( nEscLen );
+ aMemoryStream.Write( pData, nEscLen );
+ aMemoryStream.Seek( STREAM_SEEK_TO_BEGIN );
+ //#fdo39428 SvStream no longer supports operator>>(long&)
+ sal_Int32 nTmpX(0), nTmpY(0);
+ aMemoryStream >> nTmpX
+ >> nTmpY
+ >> nStringLen;
+ aPt.X() = nTmpX;
+ aPt.Y() = nTmpY;
+
+ if ( ( static_cast< sal_uInt64 >( nStringLen ) * sizeof( sal_Unicode ) ) < ( nEscLen - aMemoryStream.Tell() ) )
+ {
+
+ aString = read_uInt16s_ToOUString(aMemoryStream, nStringLen);
+ aMemoryStream >> nDXCount;
+ if ( ( static_cast< sal_uInt64 >( nDXCount ) * sizeof( sal_Int32 ) ) >= ( nEscLen - aMemoryStream.Tell() ) )
+ nDXCount = 0;
+ if ( nDXCount )
+ pDXAry = new sal_Int32[ nDXCount ];
+ for (sal_uInt32 i = 0; i < nDXCount; i++ )
+ aMemoryStream >> pDXAry[ i ];
+ aMemoryStream >> nSkipActions;
+ pOut->DrawText( aPt, aString, pDXAry );
+ delete[] pDXAry;
+ }
+ }
+ }
+ break;
+ }
+ }
+ delete[] pData;
+ }
+ }
+ }
+ else if ( (nNewMagic == static_cast< sal_uInt32 >(0x43464D57)) && (nLen >= 34) && ( (sal_Int32)(nLen + 10) <= (sal_Int32)(nRecSize * 2) ))
+ {
+ sal_uInt32 nComType = 0, nVersion = 0, nFlags = 0, nComRecCount = 0,
+ nCurRecSize = 0, nRemainingSize = 0, nEMFTotalSize = 0;
+ sal_uInt16 nCheck = 0;
+
+ *pWMF >> nComType >> nVersion >> nCheck >> nFlags
+ >> nComRecCount >> nCurRecSize
+ >> nRemainingSize >> nEMFTotalSize; // the nRemainingSize is not mentioned in MSDN documentation
+ // but it seems to be required to read in data produced by OLE
+
+ if( nComType == 0x01 && nVersion == 0x10000 && nComRecCount )
+ {
+ if( !nEMFRec )
+ { // first EMF comment
+ nEMFRecCount = nComRecCount;
+ nEMFSize = nEMFTotalSize;
+ pEMFStream = new SvMemoryStream( nEMFSize );
+ }
+ else if( ( nEMFRecCount != nComRecCount ) || ( nEMFSize != nEMFTotalSize ) ) // add additional checks here
+ {
+ // total records should be the same as in previous comments
+ nEMFRecCount = 0xFFFFFFFF;
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+ nEMFRec++;
+
+ if( pEMFStream && nCurRecSize + 34 > nLen )
+ {
+ nEMFRecCount = 0xFFFFFFFF;
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+
+ if( pEMFStream )
+ {
+ sal_Int8* pBuf = new sal_Int8[ nCurRecSize ];
+ sal_uInt32 nCount = pWMF->Read( pBuf, nCurRecSize );
+ if( nCount == nCurRecSize )
+ pEMFStream->Write( pBuf, nCount );
+ delete[] pBuf;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case W_META_SETRELABS:
+ case W_META_SETPOLYFILLMODE:
+ case W_META_SETSTRETCHBLTMODE:
+ case W_META_SETTEXTCHAREXTRA:
+ case W_META_SETTEXTJUSTIFICATION:
+ case W_META_FLOODFILL :
+ case W_META_FILLREGION:
+ case W_META_FRAMEREGION:
+ case W_META_INVERTREGION:
+ case W_META_PAINTREGION:
+ case W_META_DRAWTEXT:
+ case W_META_SETMAPPERFLAGS:
+ case W_META_SETDIBTODEV:
+ case W_META_SELECTPALETTE:
+ case W_META_REALIZEPALETTE:
+ case W_META_ANIMATEPALETTE:
+ case W_META_SETPALENTRIES:
+ case W_META_RESIZEPALETTE:
+ case W_META_EXTFLOODFILL:
+ case W_META_RESETDC:
+ case W_META_STARTDOC:
+ case W_META_STARTPAGE:
+ case W_META_ENDPAGE:
+ case W_META_ABORTDOC:
+ case W_META_ENDDOC:
+ break;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFReader::ReadHeader()
+{
+ sal_Size nStrmPos = pWMF->Tell();
+
+ sal_uInt32 nPlaceableMetaKey(0);
+ // Einlesen des METAFILEHEADER, falls vorhanden
+ *pWMF >> nPlaceableMetaKey;
+ if (!pWMF->good())
+ return false;
+
+ Rectangle aPlaceableBound;
+
+ if (nPlaceableMetaKey == 0x9ac6cdd7L)
+ { //TODO do some real error handling here
+ sal_Int16 nVal;
+
+ // Skip reserved bytes
+ pWMF->SeekRel(2);
+
+ // BoundRect
+ *pWMF >> nVal;
+ aPlaceableBound.Left() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Top() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Right() = nVal;
+ *pWMF >> nVal;
+ aPlaceableBound.Bottom() = nVal;
+
+ // inch
+ *pWMF >> nUnitsPerInch;
+
+ // reserved
+ pWMF->SeekRel( 4 );
+
+ // Skip and don't check the checksum
+ pWMF->SeekRel( 2 );
+ }
+ else
+ {
+ nUnitsPerInch = 96;
+ pWMF->Seek( nStrmPos + 18 ); // set the streampos to the start of the the metaactions
+ GetPlaceableBound( aPlaceableBound, pWMF );
+ pWMF->Seek( nStrmPos );
+ if ( pExternalHeader != NULL && ( pExternalHeader->mapMode == MM_ISOTROPIC
+ || pExternalHeader->mapMode == MM_ANISOTROPIC ) )
+ {
+ // #n417818#: If we have an external header then overwrite the bounds!
+ Rectangle aExtRect(0, 0,
+ pExternalHeader->xExt*567*nUnitsPerInch/1440/1000,
+ pExternalHeader->yExt*567*nUnitsPerInch/1440/1000);
+ GetWinExtMax( aExtRect, aPlaceableBound, pExternalHeader->mapMode );
+ pOut->SetMapMode( pExternalHeader->mapMode );
+ }
+ }
+
+ pOut->SetUnitsPerInch( nUnitsPerInch );
+ pOut->SetWinOrg( aPlaceableBound.TopLeft() );
+ Size aWMFSize( labs( aPlaceableBound.GetWidth() ), labs( aPlaceableBound.GetHeight() ) );
+ pOut->SetWinExt( aWMFSize );
+
+ Size aDevExt( 10000, 10000 );
+ if( ( labs( aWMFSize.Width() ) > 1 ) && ( labs( aWMFSize.Height() ) > 1 ) )
+ {
+ const Fraction aFrac( 1, nUnitsPerInch );
+ MapMode aWMFMap( MAP_INCH, Point(), aFrac, aFrac );
+ Size aSize100( OutputDevice::LogicToLogic( aWMFSize, aWMFMap, MAP_100TH_MM ) );
+ aDevExt = Size( labs( aSize100.Width() ), labs( aSize100.Height() ) );
+ }
+ pOut->SetDevExt( aDevExt );
+
+ // Einlesen des METAHEADER
+ sal_uInt32 nMetaKey(0);
+ *pWMF >> nMetaKey; // Typ und Headergroesse
+ if (!pWMF->good())
+ return false;
+ if (nMetaKey != 0x00090001)
+ {
+ sal_uInt16 aNextWord(0);
+ *pWMF >> aNextWord;
+ if (nMetaKey != 0x10000 || aNextWord != 0x09)
+ {
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ return false;
+ }
+ }
+
+ pWMF->SeekRel( 2 ); // Version (von Windows)
+ pWMF->SeekRel( 4 ); // Size (der Datei in Words)
+ pWMF->SeekRel( 2 ); // NoObjects (Maximale Anzahl der gleichzeitigen Objekte)
+ pWMF->SeekRel( 4 ); // MaxRecord (Groesse des groessten Records in Words)
+ pWMF->SeekRel( 2 ); // NoParameters (Unused
+
+ return pWMF->good();
+}
+
+void WMFReader::ReadWMF()
+{
+ sal_uInt16 nFunction;
+ sal_uLong nPos, nPercent, nLastPercent;
+
+ nSkipActions = 0;
+ nCurrentAction = 0;
+ nUnicodeEscapeAction = 0;
+
+ pEMFStream = NULL;
+ nEMFRecCount = 0;
+ nEMFRec = 0;
+ nEMFSize = 0;
+
+ sal_Bool bEMFAvailable = sal_False;
+
+ pOut->SetMapMode( MM_ANISOTROPIC );
+ pOut->SetWinOrg( Point() );
+ pOut->SetWinExt( Size( 1, 1 ) );
+ pOut->SetDevExt( Size( 10000, 10000 ) );
+
+ nEndPos=pWMF->Seek( STREAM_SEEK_TO_END );
+ pWMF->Seek( nStartPos );
+ Callback( (sal_uInt16) ( nLastPercent = 0 ) );
+
+ if ( ReadHeader( ) )
+ {
+
+ nPos = pWMF->Tell();
+
+ if( nEndPos - nStartPos )
+ {
+ while( sal_True )
+ {
+ nCurrentAction++;
+ nPercent = ( nPos - nStartPos ) * 100 / ( nEndPos - nStartPos );
+
+ if( nLastPercent + 4 <= nPercent )
+ {
+ Callback( (sal_uInt16) nPercent );
+ nLastPercent = nPercent;
+ }
+ *pWMF >> nRecSize >> nFunction;
+
+ if( pWMF->GetError()
+ || ( nRecSize < 3 )
+ || ( nRecSize == 3
+ && nFunction == 0
+ )
+ || pWMF->IsEof()
+ )
+ {
+ if( pWMF->IsEof() )
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+
+ break;
+ }
+ if ( !bEMFAvailable )
+ {
+ if( !aBmpSaveList.empty()
+ && ( nFunction != W_META_STRETCHDIB )
+ && ( nFunction != W_META_DIBBITBLT )
+ && ( nFunction != W_META_DIBSTRETCHBLT )
+ )
+ {
+ pOut->ResolveBitmapActions( aBmpSaveList );
+ }
+
+ if ( !nSkipActions )
+ ReadRecordParams( nFunction );
+ else
+ nSkipActions--;
+
+ if( pEMFStream && nEMFRecCount == nEMFRec )
+ {
+ GDIMetaFile aMeta;
+ pEMFStream->Seek( 0 );
+ EnhWMFReader* pEMFReader = new EnhWMFReader ( *pEMFStream, aMeta );
+ bEMFAvailable = pEMFReader->ReadEnhWMF();
+ delete pEMFReader; // destroy first!!!
+
+ if( bEMFAvailable )
+ {
+ pOut->AddFromGDIMetaFile( aMeta );
+ pOut->SetrclFrame( Rectangle( Point(0, 0), aMeta.GetPrefSize()));
+
+ // the stream needs to be set to the wmf end position,
+ // otherwise the GfxLink that is created will be incorrect
+ // (leading to graphic loss after swapout/swapin).
+ // so we will proceed normally, but are ignoring further wmf
+ // records
+ }
+ else
+ {
+ // something went wrong
+ // continue with WMF, don't try this again
+ delete pEMFStream;
+ pEMFStream = NULL;
+ }
+ }
+ }
+ nPos += nRecSize * 2;
+ if ( nPos <= nEndPos )
+ pWMF->Seek( nPos );
+ else
+ pWMF->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ }
+ else
+ pWMF->SetError( SVSTREAM_GENERALERROR );
+
+ if( !pWMF->GetError() && !aBmpSaveList.empty() )
+ pOut->ResolveBitmapActions( aBmpSaveList );
+ }
+ if ( pWMF->GetError() )
+ pWMF->Seek( nStartPos );
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFReader::GetPlaceableBound( Rectangle& rPlaceableBound, SvStream* pStm )
+{
+ sal_Bool bRet = sal_True;
+
+ rPlaceableBound.Left() = (sal_Int32)0x7fffffff;
+ rPlaceableBound.Top() = (sal_Int32)0x7fffffff;
+ rPlaceableBound.Right() = (sal_Int32)0x80000000;
+ rPlaceableBound.Bottom() = (sal_Int32)0x80000000;
+
+ sal_uInt32 nPos = pStm->Tell();
+ sal_uInt32 nEnd = pStm->Seek( STREAM_SEEK_TO_END );
+
+ pStm->Seek( nPos );
+
+ if( nEnd - nPos )
+ {
+ sal_Int16 nMapMode = MM_ANISOTROPIC;
+ sal_uInt16 nFunction;
+ sal_uInt32 nRSize;
+
+ while( bRet )
+ {
+ *pStm >> nRSize >> nFunction;
+
+ if( pStm->GetError() || ( nRSize < 3 ) || ( nRSize==3 && nFunction==0 ) || pStm->IsEof() )
+ {
+ if( pStm->IsEof() )
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ }
+ break;
+ }
+ switch( nFunction )
+ {
+ case W_META_SETWINDOWORG:
+ {
+ Point aWinOrg;
+ aWinOrg = ReadYX();
+ rPlaceableBound.SetPos( aWinOrg );
+ }
+ break;
+
+ case W_META_SETWINDOWEXT:
+ {
+ sal_Int16 nWidth(0), nHeight(0);
+ *pStm >> nHeight >> nWidth;
+ rPlaceableBound.SetSize( Size( nWidth, nHeight ) );
+ }
+ break;
+
+ case W_META_SETMAPMODE :
+ *pStm >> nMapMode;
+ break;
+
+ case W_META_MOVETO:
+ case W_META_LINETO:
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_RECTANGLE:
+ case W_META_INTERSECTCLIPRECT:
+ case W_META_EXCLUDECLIPRECT :
+ case W_META_ELLIPSE:
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_ROUNDRECT:
+ ReadYXExt(); // size
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_ARC:
+ case W_META_PIE:
+ case W_META_CHORD:
+ ReadYX(); // end
+ ReadYX(); // start
+ GetWinExtMax( ReadRectangle(), rPlaceableBound, nMapMode );
+ break;
+
+ case W_META_POLYGON:
+ {
+ sal_uInt16 nPoints;
+ *pStm >> nPoints;
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_POLYPOLYGON:
+ {
+ bool bRecordOk = true;
+ sal_uInt16 nPoly, nPoints = 0;
+ *pStm >> nPoly;
+ for(sal_uInt16 i = 0; i < nPoly; i++ )
+ {
+ sal_uInt16 nP = 0;
+ *pStm >> nP;
+ if (nP > SAL_MAX_UINT16 - nPoints)
+ {
+ bRecordOk = false;
+ break;
+ }
+ nPoints += nP;
+ }
+
+ SAL_WARN_IF(!bRecordOk, "svtools.filter", "polypolygon record has more polygons than we can handle");
+
+ bRecordOk &= pStm->good();
+
+ if (!bRecordOk)
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ break;
+ }
+
+ for (sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+
+ bRecordOk &= pStm->good();
+
+ if (!bRecordOk)
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ break;
+ }
+ }
+ break;
+
+ case W_META_POLYLINE:
+ {
+ sal_uInt16 nPoints;
+ *pStm >> nPoints;
+ for(sal_uInt16 i = 0; i < nPoints; i++ )
+ GetWinExtMax( ReadPoint(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_SETPIXEL:
+ {
+ ReadColor();
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ }
+ break;
+
+ case W_META_TEXTOUT:
+ {
+ sal_uInt16 nLength;
+ *pStm >> nLength;
+ // todo: we also have to take care of the text width
+ if ( nLength )
+ {
+ pStm->SeekRel( ( nLength + 1 ) &~ 1 );
+ GetWinExtMax( ReadYX(), rPlaceableBound, nMapMode );
+ }
+ }
+ break;
+
+ case W_META_EXTTEXTOUT:
+ {
+ sal_uInt16 nLen, nOptions;
+ Point aPosition;
+
+ aPosition = ReadYX();
+ *pStm >> nLen >> nOptions;
+ // todo: we also have to take care of the text width
+ if( nLen )
+ GetWinExtMax( aPosition, rPlaceableBound, nMapMode );
+ }
+ break;
+ case W_META_BITBLT:
+ case W_META_STRETCHBLT:
+ case W_META_DIBBITBLT:
+ case W_META_DIBSTRETCHBLT:
+ case W_META_STRETCHDIB:
+ {
+ sal_Int32 nWinROP;
+ sal_uInt16 nSx, nSy, nSxe, nSye, nUsage;
+ *pStm >> nWinROP;
+
+ if( nFunction == W_META_STRETCHDIB )
+ *pStm >> nUsage;
+
+ // nSye and nSxe is the number of pixels that has to been used
+ if( nFunction == W_META_STRETCHDIB || nFunction == W_META_STRETCHBLT || nFunction == W_META_DIBSTRETCHBLT )
+ *pStm >> nSye >> nSxe;
+ else
+ nSye = nSxe = 0; // set this to zero as indicator not to scale the bitmap later
+
+ // nSy and nx is the offset of the first pixel
+ *pStm >> nSy >> nSx;
+
+ if( nFunction == W_META_STRETCHDIB || nFunction == W_META_DIBBITBLT || nFunction == W_META_DIBSTRETCHBLT )
+ {
+ if ( nWinROP == PATCOPY )
+ *pStm >> nUsage; // i don't know anything of this parameter, so its called nUsage
+ // pOut->DrawRect( Rectangle( ReadYX(), aDestSize ), sal_False );
+
+ Size aDestSize( ReadYXExt() );
+ if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
+ {
+ Rectangle aDestRect( ReadYX(), aDestSize );
+ GetWinExtMax( aDestRect, rPlaceableBound, nMapMode );
+ }
+ }
+ }
+ break;
+
+ case W_META_PATBLT:
+ {
+ sal_uInt32 nROP;
+ *pStm >> nROP;
+ Size aSize = ReadYXExt();
+ GetWinExtMax( Rectangle( ReadYX(), aSize ), rPlaceableBound, nMapMode );
+ }
+ break;
+ }
+ nPos += nRSize * 2;
+ if ( nPos <= nEnd )
+ pStm->Seek( nPos );
+ else
+ {
+ pStm->SetError( SVSTREAM_FILEFORMAT_ERROR );
+ bRet = sal_False;
+ }
+
+ }
+ }
+ else
+ {
+ pStm->SetError( SVSTREAM_GENERALERROR );
+ bRet = sal_False;
+ }
+ return bRet;
+}
+
+WMFReader::~WMFReader()
+{
+ if( pEMFStream )
+ delete pEMFStream;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmf.cxx b/vcl/source/filter/wmf/wmf.cxx
new file mode 100644
index 000000000000..9c3b7e6dc0e7
--- /dev/null
+++ b/vcl/source/filter/wmf/wmf.cxx
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "winmtf.hxx"
+#include "emfwr.hxx"
+#include "wmfwr.hxx"
+#include <svtools/wmf.hxx>
+#include <comphelper/scopeguard.hxx>
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertWMFToGDIMetaFile( SvStream & rStreamWMF, GDIMetaFile & rGDIMetaFile, FilterConfigItem* pConfigItem, WMF_EXTERNALHEADER *pExtHeader )
+{
+ sal_uInt32 nMetaType;
+ sal_uInt32 nOrgPos = rStreamWMF.Tell();
+ sal_uInt16 nOrigNumberFormat = rStreamWMF.GetNumberFormatInt();
+ rStreamWMF.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ rStreamWMF.Seek( 0x28 );
+ rStreamWMF >> nMetaType;
+ rStreamWMF.Seek( nOrgPos );
+ if ( nMetaType == 0x464d4520 )
+ {
+ if ( EnhWMFReader( rStreamWMF, rGDIMetaFile, pConfigItem ).ReadEnhWMF() == sal_False )
+ rStreamWMF.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ else
+ {
+ WMFReader( rStreamWMF, rGDIMetaFile, pConfigItem, pExtHeader ).ReadWMF( );
+ }
+ rStreamWMF.SetNumberFormatInt( nOrigNumberFormat );
+ return !rStreamWMF.GetError();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ReadWindowMetafile( SvStream& rStream, GDIMetaFile& rMTF, FilterConfigItem* pFilterConfigItem )
+{
+ sal_uInt32 nMetaType(0);
+ sal_uInt32 nOrgPos = rStream.Tell();
+
+ sal_uInt16 nOrigNumberFormat = rStream.GetNumberFormatInt();
+ rStream.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ //exception-safe reset nOrigNumberFormat at end of scope
+ const ::comphelper::ScopeGuard aScopeGuard(
+ boost::bind(&SvStream::SetNumberFormatInt, ::boost::ref(rStream),
+ nOrigNumberFormat));
+
+ rStream.Seek( 0x28 );
+ rStream >> nMetaType;
+ rStream.Seek( nOrgPos );
+
+ if (!rStream.good())
+ return false;
+
+ if ( nMetaType == 0x464d4520 )
+ {
+ if ( EnhWMFReader( rStream, rMTF, NULL ).ReadEnhWMF() == sal_False )
+ rStream.SetError( SVSTREAM_FILEFORMAT_ERROR );
+ }
+ else
+ {
+ WMFReader( rStream, rMTF, pFilterConfigItem ).ReadWMF();
+ }
+
+ return rStream.good();
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertGDIMetaFileToWMF( const GDIMetaFile & rMTF, SvStream & rTargetStream,
+ FilterConfigItem* pConfigItem, sal_Bool bPlaceable)
+{
+ WMFWriter aWMFWriter;
+ return aWMFWriter.WriteWMF( rMTF, rTargetStream, pConfigItem, bPlaceable );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool ConvertGDIMetaFileToEMF( const GDIMetaFile & rMTF, SvStream & rTargetStream,
+ FilterConfigItem* pConfigItem )
+{
+ EMFWriter aEMFWriter(rTargetStream);
+ return aEMFWriter.WriteEMF( rMTF, pConfigItem );
+}
+
+// -----------------------------------------------------------------------------
+
+sal_Bool WriteWindowMetafileBits( SvStream& rStream, const GDIMetaFile& rMTF )
+{
+ return WMFWriter().WriteWMF( rMTF, rStream, NULL, sal_False );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmfwr.cxx b/vcl/source/filter/wmf/wmfwr.cxx
new file mode 100644
index 000000000000..c9baef6b36f5
--- /dev/null
+++ b/vcl/source/filter/wmf/wmfwr.cxx
@@ -0,0 +1,2052 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "wmfwr.hxx"
+#include <unotools/fontcvt.hxx>
+#include "emfwr.hxx"
+#include <rtl/crc.h>
+#include <rtl/tencinfo.h>
+#include <tools/bigint.hxx>
+#include <tools/helpers.hxx>
+#include <tools/tenccvt.hxx>
+#include <osl/endian.h>
+#include <i18nutil/unicode.hxx> //unicode::getUnicodeScriptType
+
+#include <vcl/metric.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+
+//====================== MS-Windows-defines ===============================
+
+#define W_META_SETBKCOLOR 0x0201
+#define W_META_SETBKMODE 0x0102
+#define W_META_SETMAPMODE 0x0103
+#define W_META_SETROP2 0x0104
+#define W_META_SETRELABS 0x0105
+#define W_META_SETPOLYFILLMODE 0x0106
+#define W_META_SETSTRETCHBLTMODE 0x0107
+#define W_META_SETTEXTCHAREXTRA 0x0108
+#define W_META_SETTEXTCOLOR 0x0209
+#define W_META_SETTEXTJUSTIFICATION 0x020A
+#define W_META_SETWINDOWORG 0x020B
+#define W_META_SETWINDOWEXT 0x020C
+#define W_META_SETVIEWPORTORG 0x020D
+#define W_META_SETVIEWPORTEXT 0x020E
+#define W_META_OFFSETWINDOWORG 0x020F
+#define W_META_SCALEWINDOWEXT 0x0410
+#define W_META_OFFSETVIEWPORTORG 0x0211
+#define W_META_SCALEVIEWPORTEXT 0x0412
+#define W_META_LINETO 0x0213
+#define W_META_MOVETO 0x0214
+#define W_META_EXCLUDECLIPRECT 0x0415
+#define W_META_INTERSECTCLIPRECT 0x0416
+#define W_META_ARC 0x0817
+#define W_META_ELLIPSE 0x0418
+#define W_META_FLOODFILL 0x0419
+#define W_META_PIE 0x081A
+#define W_META_RECTANGLE 0x041B
+#define W_META_ROUNDRECT 0x061C
+#define W_META_PATBLT 0x061D
+#define W_META_SAVEDC 0x001E
+#define W_META_SETPIXEL 0x041F
+#define W_META_OFFSETCLIPRGN 0x0220
+#define W_META_TEXTOUT 0x0521
+#define W_META_BITBLT 0x0922
+#define W_META_STRETCHBLT 0x0B23
+#define W_META_POLYGON 0x0324
+#define W_META_POLYLINE 0x0325
+#define W_META_ESCAPE 0x0626
+#define W_META_RESTOREDC 0x0127
+#define W_META_FILLREGION 0x0228
+#define W_META_FRAMEREGION 0x0429
+#define W_META_INVERTREGION 0x012A
+#define W_META_PAINTREGION 0x012B
+#define W_META_SELECTCLIPREGION 0x012C
+#define W_META_SELECTOBJECT 0x012D
+#define W_META_SETTEXTALIGN 0x012E
+#define W_META_DRAWTEXT 0x062F
+#define W_META_CHORD 0x0830
+#define W_META_SETMAPPERFLAGS 0x0231
+#define W_META_EXTTEXTOUT 0x0a32
+#define W_META_SETDIBTODEV 0x0d33
+#define W_META_SELECTPALETTE 0x0234
+#define W_META_REALIZEPALETTE 0x0035
+#define W_META_ANIMATEPALETTE 0x0436
+#define W_META_SETPALENTRIES 0x0037
+#define W_META_POLYPOLYGON 0x0538
+#define W_META_RESIZEPALETTE 0x0139
+#define W_META_DIBBITBLT 0x0940
+#define W_META_DIBSTRETCHBLT 0x0b41
+#define W_META_DIBCREATEPATTERNBRUSH 0x0142
+#define W_META_STRETCHDIB 0x0f43
+#define W_META_EXTFLOODFILL 0x0548
+#define W_META_RESETDC 0x014C
+#define W_META_STARTDOC 0x014D
+#define W_META_STARTPAGE 0x004F
+#define W_META_ENDPAGE 0x0050
+#define W_META_ABORTDOC 0x0052
+#define W_META_ENDDOC 0x005E
+#define W_META_DELETEOBJECT 0x01f0
+#define W_META_CREATEPALETTE 0x00f7
+#define W_META_CREATEBRUSH 0x00F8
+#define W_META_CREATEPATTERNBRUSH 0x01F9
+#define W_META_CREATEPENINDIRECT 0x02FA
+#define W_META_CREATEFONTINDIRECT 0x02FB
+#define W_META_CREATEBRUSHINDIRECT 0x02FC
+#define W_META_CREATEBITMAPINDIRECT 0x02FD
+#define W_META_CREATEBITMAP 0x06FE
+#define W_META_CREATEREGION 0x06FF
+
+#define W_TRANSPARENT 1
+#define W_OPAQUE 2
+
+#define W_R2_BLACK 1
+#define W_R2_NOTMERGEPEN 2
+#define W_R2_MASKNOTPEN 3
+#define W_R2_NOTCOPYPEN 4
+#define W_R2_MASKPENNOT 5
+#define W_R2_NOT 6
+#define W_R2_XORPEN 7
+#define W_R2_NOTMASKPEN 8
+#define W_R2_MASKPEN 9
+#define W_R2_NOTXORPEN 10
+#define W_R2_NOP 11
+#define W_R2_MERGENOTPEN 12
+#define W_R2_COPYPEN 13
+#define W_R2_MERGEPENNOT 14
+#define W_R2_MERGEPEN 15
+#define W_R2_WHITE 16
+
+#define W_TA_NOUPDATECP 0x0000
+#define W_TA_UPDATECP 0x0001
+#define W_TA_LEFT 0x0000
+#define W_TA_RIGHT 0x0002
+#define W_TA_CENTER 0x0006
+#define W_TA_TOP 0x0000
+#define W_TA_BOTTOM 0x0008
+#define W_TA_BASELINE 0x0018
+#define W_TA_RTLREADING 0x0100
+
+#define W_SRCCOPY 0x00CC0020L
+#define W_SRCPAINT 0x00EE0086L
+#define W_SRCAND 0x008800C6L
+#define W_SRCINVERT 0x00660046L
+#define W_SRCERASE 0x00440328L
+#define W_NOTSRCCOPY 0x00330008L
+#define W_NOTSRCERASE 0x001100A6L
+#define W_MERGECOPY 0x00C000CAL
+#define W_MERGEPAINT 0x00BB0226L
+#define W_PATCOPY 0x00F00021L
+#define W_PATPAINT 0x00FB0A09L
+#define W_PATINVERT 0x005A0049L
+#define W_DSTINVERT 0x00550009L
+#define W_BLACKNESS 0x00000042L
+#define W_WHITENESS 0x00FF0062L
+
+#define W_PS_SOLID 0
+#define W_PS_DASH 1
+#define W_PS_DOT 2
+#define W_PS_DASHDOT 3
+#define W_PS_DASHDOTDOT 4
+#define W_PS_NULL 5
+#define W_PS_INSIDEFRAME 6
+
+#define W_LF_FACESIZE 32
+
+#define W_ANSI_CHARSET 0
+#define W_DEFAULT_CHARSET 1
+#define W_SYMBOL_CHARSET 2
+#define W_SHIFTJIS_CHARSET 128
+#define W_HANGEUL_CHARSET 129
+#define W_GB2312_CHARSET 134
+#define W_CHINESEBIG5_CHARSET 136
+#define W_OEM_CHARSET 255
+/*WINVER >= 0x0400*/
+#define W_JOHAB_CHARSET 130
+#define W_HEBREW_CHARSET 177
+#define W_ARABIC_CHARSET 178
+#define W_GREEK_CHARSET 161
+#define W_TURKISH_CHARSET 162
+#define W_VIETNAMESE_CHARSET 163
+#define W_THAI_CHARSET 222
+#define W_EASTEUROPE_CHARSET 238
+#define W_RUSSIAN_CHARSET 204
+#define W_MAC_CHARSET 77
+#define W_BALTIC_CHARSET 186
+
+#define W_DEFAULT_PITCH 0x00
+#define W_FIXED_PITCH 0x01
+#define W_VARIABLE_PITCH 0x02
+
+#define W_FF_DONTCARE 0x00
+#define W_FF_ROMAN 0x10
+#define W_FF_SWISS 0x20
+#define W_FF_MODERN 0x30
+#define W_FF_SCRIPT 0x40
+#define W_FF_DECORATIVE 0x50
+
+#define W_FW_DONTCARE 0
+#define W_FW_THIN 100
+#define W_FW_EXTRALIGHT 200
+#define W_FW_LIGHT 300
+#define W_FW_NORMAL 400
+#define W_FW_MEDIUM 500
+#define W_FW_SEMIBOLD 600
+#define W_FW_BOLD 700
+#define W_FW_EXTRABOLD 800
+#define W_FW_HEAVY 900
+#define W_FW_ULTRALIGHT 200
+#define W_FW_REGULAR 400
+#define W_FW_DEMIBOLD 600
+#define W_FW_ULTRABOLD 800
+#define W_FW_BLACK 900
+
+#define W_BS_SOLID 0
+#define W_BS_HOLLOW 1
+#define W_BS_HATCHED 2
+#define W_BS_PATTERN 3
+#define W_BS_INDEXED 4
+#define W_BS_DIBPATTERN 5
+
+#define W_HS_HORIZONTAL 0
+#define W_HS_VERTICAL 1
+#define W_HS_FDIAGONAL 2
+#define W_HS_BDIAGONAL 3
+#define W_HS_CROSS 4
+#define W_HS_DIAGCROSS 5
+
+#define W_MFCOMMENT 15
+
+#define PRIVATE_ESCAPE_UNICODE 2
+
+//========================== Methoden von WMFWriter ==========================
+
+void WMFWriter::MayCallback()
+{
+ if ( xStatusIndicator.is() )
+ {
+ sal_uLong nPercent;
+
+ // Wir gehen mal einfach so davon aus, dass 16386 Actions einer Bitmap entsprechen
+ // (in der Regel wird ein Metafile entweder nur Actions oder einige Bitmaps und fast
+ // keine Actions enthalten. Dann ist das Verhaeltnis ziemlich unwichtig)
+
+ nPercent=((nWrittenBitmaps<<14)+(nActBitmapPercent<<14)/100+nWrittenActions)
+ *100
+ /((nNumberOfBitmaps<<14)+nNumberOfActions);
+
+ if ( nPercent >= nLastPercent + 3 )
+ {
+ nLastPercent = nPercent;
+ if( nPercent <= 100 )
+ xStatusIndicator->setValue( nPercent );
+ }
+ }
+}
+
+void WMFWriter::CountActionsAndBitmaps( const GDIMetaFile & rMTF )
+{
+ size_t nAction, nActionCount;
+
+ nActionCount = rMTF.GetActionSize();
+
+ for ( nAction=0; nAction < nActionCount; nAction++ )
+ {
+ MetaAction* pMA = rMTF.GetAction( nAction );
+
+ switch( pMA->GetType() )
+ {
+ case META_BMP_ACTION:
+ case META_BMPSCALE_ACTION:
+ case META_BMPSCALEPART_ACTION:
+ case META_BMPEX_ACTION:
+ case META_BMPEXSCALE_ACTION:
+ case META_BMPEXSCALEPART_ACTION:
+ nNumberOfBitmaps++;
+ break;
+ }
+ nNumberOfActions++;
+ }
+}
+
+
+void WMFWriter::WritePointXY(const Point & rPoint)
+{
+ Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aPt.X()) << ((short)aPt.Y());
+}
+
+
+void WMFWriter::WritePointYX(const Point & rPoint)
+{
+ Point aPt( pVirDev->LogicToLogic(rPoint,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aPt.Y()) << ((short)aPt.X());
+}
+
+
+sal_Int32 WMFWriter::ScaleWidth( sal_Int32 nDX )
+{
+ Size aSz( pVirDev->LogicToLogic(Size(nDX,0),aSrcMapMode,aTargetMapMode) );
+ return aSz.Width();
+}
+
+
+void WMFWriter::WriteSize(const Size & rSize)
+{
+ Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aSz.Width()) << ((short)aSz.Height());
+}
+
+
+void WMFWriter::WriteHeightWidth(const Size & rSize)
+{
+ Size aSz( pVirDev->LogicToLogic(rSize,aSrcMapMode,aTargetMapMode) );
+ *pWMF << ((short)aSz.Height()) << ((short)aSz.Width());
+}
+
+
+void WMFWriter::WriteRectangle(const Rectangle & rRect)
+{
+ WritePointYX(Point(rRect.Right()+1,rRect.Bottom()+1));
+ WritePointYX(rRect.TopLeft());
+}
+
+
+void WMFWriter::WriteColor(const Color & rColor)
+{
+ *pWMF << (sal_uInt8) rColor.GetRed() << (sal_uInt8) rColor.GetGreen() << (sal_uInt8) rColor.GetBlue() << (sal_uInt8) 0;
+}
+
+
+void WMFWriter::WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType)
+{
+ nActRecordPos=pWMF->Tell();
+ if (nSizeWords>nMaxRecordSize) nMaxRecordSize=nSizeWords;
+ *pWMF << nSizeWords << nType;
+}
+
+
+void WMFWriter::UpdateRecordHeader()
+{
+ sal_uLong nPos;
+ sal_uInt32 nSize;
+
+ nPos=pWMF->Tell(); nSize=nPos-nActRecordPos;
+ if ((nSize & 1)!=0) {
+ *pWMF << (sal_uInt8)0;
+ nPos++; nSize++;
+ }
+ nSize/=2;
+ if (nSize>nMaxRecordSize) nMaxRecordSize=nSize;
+ pWMF->Seek(nActRecordPos);
+ *pWMF << nSize;
+ pWMF->Seek(nPos);
+}
+
+
+void WMFWriter::WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_ARC);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+void WMFWriter::WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_CHORD);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_CreateBrushIndirect(const Color& rColor)
+{
+ WriteRecordHeader(0x00000007,W_META_CREATEBRUSHINDIRECT);
+
+ if( rColor==Color(COL_TRANSPARENT) )
+ *pWMF << (sal_uInt16) W_BS_HOLLOW;
+ else
+ *pWMF << (sal_uInt16) W_BS_SOLID;
+
+ WriteColor( rColor );
+ *pWMF << (sal_uInt16) 0;
+}
+
+
+void WMFWriter::WMFRecord_CreateFontIndirect(const Font & rFont)
+{
+ sal_uInt16 nWeight,i;
+ sal_uInt8 nPitchFamily;
+
+ WriteRecordHeader(0x00000000,W_META_CREATEFONTINDIRECT);
+ WriteHeightWidth(Size(rFont.GetSize().Width(),-rFont.GetSize().Height()));
+ *pWMF << (short)rFont.GetOrientation() << (short)rFont.GetOrientation();
+
+ switch (rFont.GetWeight()) {
+ case WEIGHT_THIN: nWeight=W_FW_THIN; break;
+ case WEIGHT_ULTRALIGHT: nWeight=W_FW_ULTRALIGHT; break;
+ case WEIGHT_LIGHT: nWeight=W_FW_LIGHT; break;
+ case WEIGHT_SEMILIGHT: nWeight=W_FW_LIGHT; break;
+ case WEIGHT_NORMAL: nWeight=W_FW_NORMAL; break;
+ case WEIGHT_MEDIUM: nWeight=W_FW_MEDIUM; break;
+ case WEIGHT_SEMIBOLD: nWeight=W_FW_SEMIBOLD; break;
+ case WEIGHT_BOLD: nWeight=W_FW_BOLD; break;
+ case WEIGHT_ULTRABOLD: nWeight=W_FW_ULTRABOLD; break;
+ case WEIGHT_BLACK: nWeight=W_FW_BLACK; break;
+ default: nWeight=W_FW_DONTCARE;
+ }
+ *pWMF << nWeight;
+
+ if (rFont.GetItalic()==ITALIC_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+ if (rFont.GetUnderline()==UNDERLINE_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+ if (rFont.GetStrikeout()==STRIKEOUT_NONE) *pWMF << (sal_uInt8)0; else *pWMF << (sal_uInt8)1;
+
+ CharSet eFontNameEncoding = rFont.GetCharSet();
+ sal_uInt8 nCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontNameEncoding );
+ if ( eFontNameEncoding == RTL_TEXTENCODING_SYMBOL )
+ eFontNameEncoding = RTL_TEXTENCODING_MS_1252;
+ if ( nCharSet == 1 )
+ nCharSet = W_ANSI_CHARSET;
+ *pWMF << nCharSet;
+
+ *pWMF << (sal_uInt8)0 << (sal_uInt8)0 << (sal_uInt8)0;
+
+ switch (rFont.GetPitch()) {
+ case PITCH_FIXED: nPitchFamily=W_FIXED_PITCH; break;
+ case PITCH_VARIABLE: nPitchFamily=W_VARIABLE_PITCH; break;
+ default: nPitchFamily=W_DEFAULT_PITCH;
+ }
+ switch (rFont.GetFamily()) {
+ case FAMILY_DECORATIVE: nPitchFamily|=W_FF_DECORATIVE; break;
+ case FAMILY_MODERN: nPitchFamily|=W_FF_MODERN; break;
+ case FAMILY_ROMAN: nPitchFamily|=W_FF_ROMAN; break;
+ case FAMILY_SCRIPT: nPitchFamily|=W_FF_SCRIPT; break;
+ case FAMILY_SWISS: nPitchFamily|=W_FF_SWISS; break;
+ default: nPitchFamily|=W_FF_DONTCARE;
+ }
+ *pWMF << nPitchFamily;
+
+ rtl::OString aFontName(rtl::OUStringToOString(rFont.GetName(), eFontNameEncoding));
+ for ( i = 0; i < W_LF_FACESIZE; i++ )
+ {
+ sal_Char nChar = ( i < aFontName.getLength() ) ? aFontName[i] : 0;
+ *pWMF << nChar;
+ }
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo )
+{
+ WriteRecordHeader(0x00000008,W_META_CREATEPENINDIRECT);
+ sal_uInt16 nStyle = rColor == Color( COL_TRANSPARENT ) ? W_PS_NULL : W_PS_SOLID;
+ switch( rLineInfo.GetStyle() )
+ {
+ case LINE_DASH :
+ {
+ if ( rLineInfo.GetDotCount() )
+ {
+ if ( !rLineInfo.GetDashCount() )
+ nStyle = W_PS_DOT;
+ else
+ {
+ if ( !rLineInfo.GetDotCount() == 1 )
+ nStyle = W_PS_DASHDOT;
+ else
+ nStyle = W_PS_DASHDOTDOT;
+ }
+ }
+ else
+ nStyle = W_PS_DASH;
+ }
+ break;
+ case LINE_NONE :
+ nStyle = W_PS_NULL;
+ break;
+ default:
+ break;
+ }
+ *pWMF << nStyle;
+
+ WriteSize( Size( rLineInfo.GetWidth(), 0 ) );
+ WriteColor( rColor );
+}
+
+void WMFWriter::WMFRecord_DeleteObject(sal_uInt16 nObjectHandle)
+{
+ WriteRecordHeader(0x00000004,W_META_DELETEOBJECT);
+ *pWMF << nObjectHandle;
+}
+
+
+void WMFWriter::WMFRecord_Ellipse(const Rectangle & rRect)
+{
+ WriteRecordHeader(0x00000007,W_META_ELLIPSE);
+ WriteRectangle(rRect);
+}
+
+bool IsStarSymbol(const String &rStr)
+{
+ return rStr.EqualsIgnoreCaseAscii("starsymbol") ||
+ rStr.EqualsIgnoreCaseAscii("opensymbol");
+}
+
+void WMFWriter::WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData )
+{
+#ifdef OSL_BIGENDIAN
+ sal_uInt32 nTmp = OSL_SWAPDWORD( nEsc );
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nTmp, 4 );
+#else
+ sal_uInt32 nCheckSum = rtl_crc32( 0, &nEsc, 4 );
+#endif
+ if ( nLen )
+ nCheckSum = rtl_crc32( nCheckSum, pData, nLen );
+
+ WriteRecordHeader( 3 + 9 + ( ( nLen + 1 ) >> 1 ), W_META_ESCAPE );
+ *pWMF << (sal_uInt16)W_MFCOMMENT
+ << (sal_uInt16)( nLen + 14 ) // we will always have a fourteen byte escape header:
+ << (sal_uInt16)0x4f4f // OO
+ << (sal_uInt32)0xa2c2a // evil magic number
+ << (sal_uInt32)nCheckSum // crc32 checksum about nEsc & pData
+ << (sal_uInt32)nEsc; // escape number
+ pWMF->Write( pData, nLen );
+ if ( nLen & 1 )
+ *pWMF << (sal_uInt8)0; // pad byte
+}
+
+/* if return value is true, then a complete unicode string and also a polygon replacement has been written,
+ so there is no more action necessary
+*/
+sal_Bool WMFWriter::WMFRecord_Escape_Unicode( const Point& rPoint, const String& rUniStr, const sal_Int32* pDXAry )
+{
+ sal_Bool bEscapeUsed = sal_False;
+
+ sal_uInt32 i, nStringLen = rUniStr.Len();
+ if ( nStringLen )
+ {
+ // first we will check if a comment is necessary
+ if ( aSrcFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ) // symbol is always byte character, so there is no unicode loss
+ {
+ const sal_Unicode* pBuf = rUniStr.GetBuffer();
+ const rtl_TextEncoding aTextEncodingOrg = aSrcFont.GetCharSet();
+ rtl::OString aByteStr(rtl::OUStringToOString(rUniStr, aTextEncodingOrg));
+ rtl::OUString aUniStr2(rtl::OStringToOUString(aByteStr, aTextEncodingOrg));
+ const sal_Unicode* pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
+ for ( i = 0; i < nStringLen; i++ )
+ {
+ if ( *pBuf++ != *pConversion++ )
+ break;
+ }
+
+ if ( i != nStringLen ) // after conversion the characters are not original,
+ { // try again, with determining a better charset from unicode char
+ pBuf = rUniStr.GetBuffer();
+ const sal_Unicode* pCheckChar = pBuf;
+ rtl_TextEncoding aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the first character
+ for ( i = 1; i < nStringLen; i++)
+ {
+ if (aTextEncoding != aTextEncodingOrg) // found something
+ break;
+ pCheckChar++;
+ aTextEncoding = getBestMSEncodingByChar(*pCheckChar); // try the next character
+ }
+
+ aByteStr = rtl::OUStringToOString(rUniStr, aTextEncoding);
+ aUniStr2 = rtl::OStringToOUString(aByteStr, aTextEncoding);
+ pConversion = aUniStr2.getStr(); // this is the unicode array after bytestring <-> unistring conversion
+ for ( i = 0; i < nStringLen; i++ )
+ {
+ if ( *pBuf++ != *pConversion++ )
+ break;
+ }
+ if (i == nStringLen)
+ {
+ aSrcFont.SetCharSet (aTextEncoding);
+ SetAllAttr();
+ }
+ }
+
+ if ( ( i != nStringLen ) || IsStarSymbol( aSrcFont.GetName() ) ) // after conversion the characters are not original, so we
+ { // will store the unicode string and a polypoly replacement
+ Color aOldFillColor( aSrcFillColor );
+ Color aOldLineColor( aSrcLineColor );
+ aSrcLineInfo = LineInfo();
+ aSrcFillColor = aSrcTextColor;
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ SetLineAndFillAttr();
+ pVirDev->SetFont( aSrcFont );
+ std::vector<PolyPolygon> aPolyPolyVec;
+ if ( pVirDev->GetTextOutlines( aPolyPolyVec, rUniStr ) )
+ {
+ sal_uInt32 nDXCount = pDXAry ? nStringLen : 0;
+ sal_uInt32 nSkipActions = aPolyPolyVec.size();
+ sal_Int32 nStrmLen = 8 +
+ + sizeof( nStringLen ) + ( nStringLen * 2 )
+ + sizeof( nDXCount ) + ( nDXCount * 4 )
+ + sizeof( nSkipActions );
+
+ SvMemoryStream aMemoryStream( nStrmLen );
+ Point aPt( pVirDev->LogicToLogic( rPoint, aSrcMapMode, aTargetMapMode ) );
+ aMemoryStream << static_cast<sal_Int32>(aPt.X())
+ << static_cast<sal_Int32>(aPt.Y())
+ << nStringLen;
+ for ( i = 0; i < nStringLen; i++ )
+ aMemoryStream << rUniStr.GetChar( (sal_uInt16)i );
+ aMemoryStream << nDXCount;
+ for ( i = 0; i < nDXCount; i++ )
+ aMemoryStream << pDXAry[ i ];
+ aMemoryStream << nSkipActions;
+ WMFRecord_Escape( PRIVATE_ESCAPE_UNICODE, nStrmLen, (const sal_Int8*)aMemoryStream.GetData() );
+
+ std::vector<PolyPolygon>::iterator aIter( aPolyPolyVec.begin() );
+ while ( aIter != aPolyPolyVec.end() )
+ {
+ PolyPolygon aPolyPoly( *aIter++ );
+ aPolyPoly.Move( rPoint.X(), rPoint.Y() );
+ WMFRecord_PolyPolygon( aPolyPoly );
+ }
+ aSrcFillColor = aOldFillColor;
+ aSrcLineColor = aOldLineColor;
+ bEscapeUsed = sal_True;
+ }
+ }
+ }
+ }
+ return bEscapeUsed;
+}
+
+void WMFWriter::WMFRecord_ExtTextOut( const Point & rPoint,
+ const String & rString, const sal_Int32 * pDXAry )
+{
+ sal_uInt16 nOriginalTextLen = rString.Len();
+
+ if ( (nOriginalTextLen <= 1) || (pDXAry == NULL) )
+ {
+ WMFRecord_TextOut(rPoint, rString);
+ return;
+ }
+ rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
+ rtl::OString aByteString(rtl::OUStringToOString(rString, eChrSet));
+ TrueExtTextOut(rPoint,rString,aByteString,pDXAry);
+}
+
+void WMFWriter::TrueExtTextOut( const Point & rPoint, const String & rString,
+ const rtl::OString& rByteString, const sal_Int32 * pDXAry )
+{
+ WriteRecordHeader( 0, W_META_EXTTEXTOUT );
+ WritePointYX( rPoint );
+ sal_uInt16 nNewTextLen = static_cast<sal_uInt16>(rByteString.getLength());
+ *pWMF << nNewTextLen << (sal_uInt16)0;
+ write_uInt8s_FromOString(*pWMF, rByteString, nNewTextLen);
+ if ( nNewTextLen & 1 )
+ *pWMF << (sal_uInt8)0;
+
+ sal_uInt16 nOriginalTextLen = rString.Len();
+ sal_Int16* pConvertedDXAry = new sal_Int16[ nOriginalTextLen ];
+ sal_Int32 j = 0;
+ pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ 0 ] );
+ for (sal_uInt16 i = 1; i < ( nOriginalTextLen - 1 ); ++i)
+ pConvertedDXAry[ j++ ] = (sal_Int16)ScaleWidth( pDXAry[ i ] - pDXAry[ i - 1 ] );
+ pConvertedDXAry[ j ] = (sal_Int16)ScaleWidth( pDXAry[ nOriginalTextLen - 2 ] / ( nOriginalTextLen - 1 ) );
+
+ for (sal_uInt16 i = 0; i < nOriginalTextLen; ++i)
+ {
+ sal_Int16 nDx = pConvertedDXAry[ i ];
+ *pWMF << nDx;
+ if ( nOriginalTextLen < nNewTextLen )
+ {
+ sal_Unicode nUniChar = rString.GetChar(i);
+ rtl::OString aTemp(&nUniChar, 1, aSrcFont.GetCharSet());
+ j = aTemp.getLength();
+ while ( --j > 0 )
+ *pWMF << (sal_uInt16)0;
+ }
+ }
+ delete[] pConvertedDXAry;
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_LineTo(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_LINETO);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_MoveTo(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_MOVETO);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt)
+{
+ WriteRecordHeader(0x0000000b,W_META_PIE);
+ WritePointYX(rEndPt);
+ WritePointYX(rStartPt);
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_Polygon(const Polygon & rPoly)
+{
+ sal_uInt16 nSize,i;
+
+ Polygon aSimplePoly;
+ if ( rPoly.HasFlags() )
+ rPoly.AdaptiveSubdivide( aSimplePoly );
+ else
+ aSimplePoly = rPoly;
+ nSize = aSimplePoly.GetSize();
+ WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYGON);
+ *pWMF << nSize;
+ for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
+}
+
+
+void WMFWriter::WMFRecord_PolyLine(const Polygon & rPoly)
+{
+ sal_uInt16 nSize,i;
+ Polygon aSimplePoly;
+ if ( rPoly.HasFlags() )
+ rPoly.AdaptiveSubdivide( aSimplePoly );
+ else
+ aSimplePoly = rPoly;
+ nSize=aSimplePoly.GetSize();
+ WriteRecordHeader(((sal_uLong)nSize)*2+4,W_META_POLYLINE);
+ *pWMF << nSize;
+ for (i=0; i<nSize; i++) WritePointXY(aSimplePoly.GetPoint(i));
+}
+
+
+void WMFWriter::WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly)
+{
+ const Polygon * pPoly;
+ sal_uInt16 nCount,nSize,i,j;
+
+ nCount=rPolyPoly.Count();
+ PolyPolygon aSimplePolyPoly( rPolyPoly );
+ for ( i = 0; i < nCount; i++ )
+ {
+ if ( aSimplePolyPoly[ i ].HasFlags() )
+ {
+ Polygon aSimplePoly;
+ aSimplePolyPoly[ i ].AdaptiveSubdivide( aSimplePoly );
+ aSimplePolyPoly[ i ] = aSimplePoly;
+ }
+ }
+ WriteRecordHeader(0,W_META_POLYPOLYGON);
+ *pWMF << nCount;
+ for (i=0; i<nCount; i++) *pWMF << ((sal_uInt16)(aSimplePolyPoly.GetObject(i).GetSize()));
+ for (i=0; i<nCount; i++) {
+ pPoly=&(aSimplePolyPoly.GetObject(i));
+ nSize=pPoly->GetSize();
+ for (j=0; j<nSize; j++) WritePointXY(pPoly->GetPoint(j));
+ }
+ UpdateRecordHeader();
+}
+
+
+void WMFWriter::WMFRecord_Rectangle(const Rectangle & rRect)
+{
+ WriteRecordHeader( 0x00000007,W_META_RECTANGLE );
+ WriteRectangle( rRect );
+}
+
+
+void WMFWriter::WMFRecord_RestoreDC()
+{
+ WriteRecordHeader(0x00000004,W_META_RESTOREDC);
+ *pWMF << (short)-1;
+}
+
+
+void WMFWriter::WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound)
+{
+ WriteRecordHeader(0x00000009,W_META_ROUNDRECT);
+ WriteHeightWidth(Size(nHorzRound,nVertRound));
+ WriteRectangle(rRect);
+}
+
+
+void WMFWriter::WMFRecord_SaveDC()
+{
+ WriteRecordHeader(0x00000003,W_META_SAVEDC);
+}
+
+
+void WMFWriter::WMFRecord_SelectObject(sal_uInt16 nObjectHandle)
+{
+ WriteRecordHeader(0x00000004,W_META_SELECTOBJECT);
+ *pWMF << nObjectHandle;
+}
+
+
+void WMFWriter::WMFRecord_SetBkMode(sal_Bool bTransparent)
+{
+ WriteRecordHeader(0x00000004,W_META_SETBKMODE);
+ if (bTransparent==sal_True) *pWMF << (sal_uInt16)W_TRANSPARENT;
+ else *pWMF << (sal_uInt16)W_OPAQUE;
+}
+
+void WMFWriter::WMFRecord_SetStretchBltMode()
+{
+ WriteRecordHeader( 0x00000004, W_META_SETSTRETCHBLTMODE );
+ *pWMF << (sal_uInt16) 3; // STRETCH_DELETESCANS
+}
+
+void WMFWriter::WMFRecord_SetPixel(const Point & rPoint, const Color & rColor)
+{
+ WriteRecordHeader(0x00000007,W_META_SETPIXEL);
+ WriteColor(rColor);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_SetROP2(RasterOp eROP)
+{
+ sal_uInt16 nROP2;
+
+ switch (eROP) {
+ case ROP_INVERT: nROP2=W_R2_NOT; break;
+ case ROP_XOR: nROP2=W_R2_XORPEN; break;
+ default: nROP2=W_R2_COPYPEN;
+ }
+ WriteRecordHeader(0x00000004,W_META_SETROP2);
+ *pWMF << nROP2;
+}
+
+
+void WMFWriter::WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign)
+{
+ sal_uInt16 nAlign;
+
+ switch (eFontAlign) {
+ case ALIGN_TOP: nAlign=W_TA_TOP; break;
+ case ALIGN_BOTTOM: nAlign=W_TA_BOTTOM; break;
+ default: nAlign=W_TA_BASELINE;
+ }
+ nAlign|=eHorTextAlign;
+ nAlign|=W_TA_NOUPDATECP;
+
+ WriteRecordHeader(0x00000004,W_META_SETTEXTALIGN);
+ *pWMF << nAlign;
+}
+
+
+void WMFWriter::WMFRecord_SetTextColor(const Color & rColor)
+{
+ WriteRecordHeader(0x00000005,W_META_SETTEXTCOLOR);
+ WriteColor(rColor);
+}
+
+
+void WMFWriter::WMFRecord_SetWindowExt(const Size & rSize)
+{
+ WriteRecordHeader(0x00000005,W_META_SETWINDOWEXT);
+ WriteHeightWidth(rSize);
+}
+
+
+void WMFWriter::WMFRecord_SetWindowOrg(const Point & rPoint)
+{
+ WriteRecordHeader(0x00000005,W_META_SETWINDOWORG);
+ WritePointYX(rPoint);
+}
+
+
+void WMFWriter::WMFRecord_StretchDIB( const Point & rPoint, const Size & rSize,
+ const Bitmap & rBitmap, sal_uInt32 nROP )
+{
+ sal_uLong nPosAnf,nPosEnd;
+
+ nActBitmapPercent=50;
+ MayCallback();
+
+ WriteRecordHeader(0x00000000,W_META_STRETCHDIB);
+
+ // Die Reihenfolge im Metafile soll jetzt sein:
+ // einige Parameter (laenge 22), dann die Bitmap ohne FILEHEADER.
+ // Da aber *pWMF << rBitmap einen FILEHEADER der Laenge 14
+ // erzeugt, schreiben wir zuerst die Bitmap an die richtige Position
+ // Und ueberschreiben hinterher den FILEHEADER mit den Parametern.
+ nPosAnf=pWMF->Tell(); // Position merken, wo Parameter hin sollen
+ *pWMF << (sal_Int32)0 << (sal_Int32)0; // 8 bytes auffuellen (diese 8 bytes +
+ // 14 bytes ueberfluessigen FILEHEADER
+ // = 22 bytes Parameter)
+ *pWMF << rBitmap; // Bitmap schreiben
+
+ // Parameter schreiben:
+ nPosEnd=pWMF->Tell();
+ pWMF->Seek(nPosAnf);
+
+ // Raster-Op bestimmen, falls nichts uebergeben wurde
+ if( !nROP )
+ {
+ switch( eSrcRasterOp )
+ {
+ case ROP_INVERT: nROP = W_DSTINVERT; break;
+ case ROP_XOR: nROP = W_SRCINVERT; break;
+ default: nROP = W_SRCCOPY;
+ }
+ }
+
+ *pWMF << nROP <<
+ (short) 0 <<
+ (short) rBitmap.GetSizePixel().Height() <<
+ (short) rBitmap.GetSizePixel().Width() <<
+ (short) 0 <<
+ (short) 0;
+
+ WriteHeightWidth(rSize);
+ WritePointYX(rPoint);
+ pWMF->Seek(nPosEnd);
+
+ UpdateRecordHeader();
+
+ nWrittenBitmaps++;
+ nActBitmapPercent=0;
+}
+
+
+void WMFWriter::WMFRecord_TextOut(const Point & rPoint, const String & rStr)
+{
+ rtl_TextEncoding eChrSet = aSrcFont.GetCharSet();
+ rtl::OString aString(rtl::OUStringToOString(rStr, eChrSet));
+ TrueTextOut(rPoint, aString);
+}
+
+void WMFWriter::TrueTextOut(const Point & rPoint, const rtl::OString& rString)
+{
+ WriteRecordHeader(0,W_META_TEXTOUT);
+
+ write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(*pWMF, rString);
+ sal_Int32 nLen = rString.getLength();
+ if ((nLen&1)!=0) *pWMF << (sal_uInt8)0;
+ WritePointYX(rPoint);
+ UpdateRecordHeader();
+}
+
+void WMFWriter::WMFRecord_EndOfFile()
+{
+ WriteRecordHeader(0x00000003,0x0000);
+}
+
+
+void WMFWriter::WMFRecord_IntersectClipRect( const Rectangle& rRect )
+{
+ WriteRecordHeader( 0x00000007, W_META_INTERSECTCLIPRECT );
+ WriteRectangle(rRect);
+}
+
+
+sal_uInt16 WMFWriter::AllocHandle()
+{
+ sal_uInt16 i;
+
+ for (i=0; i<MAXOBJECTHANDLES; i++) {
+ if (bHandleAllocated[i]==sal_False) {
+ bHandleAllocated[i]=sal_True;
+ return i;
+ }
+ }
+ bStatus=sal_False;
+ return 0xffff;
+}
+
+
+void WMFWriter::FreeHandle(sal_uInt16 nObjectHandle)
+{
+ if (nObjectHandle<MAXOBJECTHANDLES) bHandleAllocated[nObjectHandle]=sal_False;
+}
+
+
+void WMFWriter::CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo )
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstPenHandle;
+ nDstPenHandle=AllocHandle();
+ WMFRecord_CreatePenIndirect( rColor, rLineInfo );
+ WMFRecord_SelectObject(nDstPenHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::CreateSelectDeleteFont(const Font & rFont)
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstFontHandle;
+ nDstFontHandle=AllocHandle();
+ WMFRecord_CreateFontIndirect(rFont);
+ WMFRecord_SelectObject(nDstFontHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::CreateSelectDeleteBrush(const Color& rColor)
+{
+ sal_uInt16 nOldHandle;
+
+ nOldHandle=nDstBrushHandle;
+ nDstBrushHandle=AllocHandle();
+ WMFRecord_CreateBrushIndirect(rColor);
+ WMFRecord_SelectObject(nDstBrushHandle);
+ if (nOldHandle<MAXOBJECTHANDLES) {
+ WMFRecord_DeleteObject(nOldHandle);
+ FreeHandle(nOldHandle);
+ }
+}
+
+
+void WMFWriter::SetLineAndFillAttr()
+{
+ if ( eDstROP2 != eSrcRasterOp )
+ {
+ eDstROP2=eSrcRasterOp;
+ WMFRecord_SetROP2(eDstROP2);
+ }
+ if ( ( aDstLineColor != aSrcLineColor ) || ( aDstLineInfo != aSrcLineInfo ) )
+ {
+ aDstLineColor = aSrcLineColor;
+ aDstLineInfo = aSrcLineInfo;
+ CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
+ }
+ if ( aDstFillColor != aSrcFillColor )
+ {
+ aDstFillColor = aSrcFillColor;
+ CreateSelectDeleteBrush( aDstFillColor );
+ }
+ if ( bDstIsClipping != bSrcIsClipping ||
+ (bSrcIsClipping==sal_True && aDstClipRegion!=aSrcClipRegion)) {
+ bDstIsClipping=bSrcIsClipping;
+ aDstClipRegion=aSrcClipRegion;
+ }
+}
+
+void WMFWriter::SetAllAttr()
+{
+ SetLineAndFillAttr();
+ if ( aDstTextColor != aSrcTextColor )
+ {
+ aDstTextColor = aSrcTextColor;
+ WMFRecord_SetTextColor(aDstTextColor);
+ }
+ if ( eDstTextAlign != eSrcTextAlign || eDstHorTextAlign != eSrcHorTextAlign )
+ {
+ eDstTextAlign = eSrcTextAlign;
+ eDstHorTextAlign = eSrcHorTextAlign;
+ WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
+ }
+ if ( aDstFont != aSrcFont )
+ {
+ pVirDev->SetFont(aSrcFont);
+ if ( aDstFont.GetName() != aSrcFont.GetName() )
+ {
+ FontCharMap aFontCharMap;
+ if ( pVirDev->GetFontCharMap( aFontCharMap ) )
+ {
+ if ( ( aFontCharMap.GetFirstChar() & 0xff00 ) == 0xf000 )
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
+ else if ( aSrcFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
+ }
+ }
+ aDstFont = aSrcFont;
+ CreateSelectDeleteFont(aDstFont);
+ }
+}
+
+
+void WMFWriter::HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon)
+{
+ if(rLinePolygon.count())
+ {
+ basegfx::B2DPolyPolygon aLinePolyPolygon(rLinePolygon);
+ basegfx::B2DPolyPolygon aFillPolyPolygon;
+
+ rInfo.applyToB2DPolyPolygon(aLinePolyPolygon, aFillPolyPolygon);
+
+ if(aLinePolyPolygon.count())
+ {
+ aSrcLineInfo = rInfo;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++)
+ {
+ const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a));
+ WMFRecord_PolyLine(Polygon(aCandidate));
+ }
+ }
+
+ if(aFillPolyPolygon.count())
+ {
+ const Color aOldLineColor(aSrcLineColor);
+ const Color aOldFillColor(aSrcFillColor);
+
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ aSrcFillColor = aOldLineColor;
+ SetLineAndFillAttr();
+
+ for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++)
+ {
+ const Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a));
+ WMFRecord_Polygon(Polygon(aPolygon));
+ }
+
+ aSrcLineColor = aOldLineColor;
+ aSrcFillColor = aOldFillColor;
+ SetLineAndFillAttr();
+ }
+ }
+}
+
+void WMFWriter::WriteRecords( const GDIMetaFile & rMTF )
+{
+ MetaAction* pMA;
+
+ if( bStatus )
+ {
+ size_t nACount = rMTF.GetActionSize();
+
+ WMFRecord_SetStretchBltMode();
+
+ for( size_t nA = 0; nA < nACount; nA++ )
+ {
+ pMA = rMTF.GetAction( nA );
+
+ switch( pMA->GetType() )
+ {
+ case META_PIXEL_ACTION:
+ {
+ const MetaPixelAction* pA = (const MetaPixelAction *) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_SetPixel( pA->GetPoint(), pA->GetColor() );
+ }
+ break;
+
+ case META_POINT_ACTION:
+ {
+ const MetaPointAction* pA = (const MetaPointAction*) pMA;
+ const Point& rPt = pA->GetPoint();
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_MoveTo( rPt);
+ WMFRecord_LineTo( rPt );
+ }
+ break;
+
+ case META_LINE_ACTION:
+ {
+ const MetaLineAction* pA = (const MetaLineAction *) pMA;
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_MoveTo( pA->GetStartPoint() );
+ WMFRecord_LineTo( pA->GetEndPoint() );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ basegfx::B2DPolygon aPolygon;
+ aPolygon.append(basegfx::B2DPoint(pA->GetStartPoint().X(), pA->GetStartPoint().Y()));
+ aPolygon.append(basegfx::B2DPoint(pA->GetEndPoint().X(), pA->GetEndPoint().Y()));
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), aPolygon);
+ }
+ }
+ break;
+
+ case META_RECT_ACTION:
+ {
+ const MetaRectAction* pA = (const MetaRectAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Rectangle( pA->GetRect() );
+ }
+ break;
+
+ case META_ROUNDRECT_ACTION:
+ {
+ const MetaRoundRectAction* pA = (const MetaRoundRectAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_RoundRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
+ }
+ break;
+
+ case META_ELLIPSE_ACTION:
+ {
+ const MetaEllipseAction* pA = (const MetaEllipseAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Ellipse( pA->GetRect() );
+ }
+ break;
+
+ case META_ARC_ACTION:
+ {
+ const MetaArcAction* pA = (const MetaArcAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Arc( pA->GetRect(),pA->GetStartPoint(),pA->GetEndPoint() );
+ }
+ break;
+
+ case META_PIE_ACTION:
+ {
+ const MetaPieAction* pA = (const MetaPieAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Pie( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+
+ case META_CHORD_ACTION:
+ {
+ const MetaChordAction* pA = (const MetaChordAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Chord( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ break;
+
+ case META_POLYLINE_ACTION:
+ {
+ const MetaPolyLineAction* pA = (const MetaPolyLineAction*) pMA;
+ const Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ if(pA->GetLineInfo().IsDefault())
+ {
+ aSrcLineInfo = pA->GetLineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyLine( rPoly );
+ }
+ else
+ {
+ // LineInfo used; handle Dash/Dot and fat lines
+ HandleLineInfoPolyPolygons(pA->GetLineInfo(), rPoly.getB2DPolygon());
+ }
+ }
+ }
+ break;
+
+ case META_POLYGON_ACTION:
+ {
+ const MetaPolygonAction* pA = (const MetaPolygonAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Polygon( pA->GetPolygon() );
+ }
+ break;
+
+ case META_POLYPOLYGON_ACTION:
+ {
+ const MetaPolyPolygonAction* pA = (const MetaPolyPolygonAction*) pMA;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyPolygon( pA->GetPolyPolygon() );
+ }
+ break;
+
+ case META_TEXTRECT_ACTION:
+ {
+ const MetaTextRectAction * pA = (const MetaTextRectAction*)pMA;
+ String aTemp( pA->GetText() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+
+ Point aPos( pA->GetRect().TopLeft() );
+ if ( !WMFRecord_Escape_Unicode( aPos, aTemp, NULL ) )
+ WMFRecord_TextOut( aPos, aTemp );
+ }
+ break;
+
+ case META_TEXT_ACTION:
+ {
+ const MetaTextAction * pA = (const MetaTextAction*) pMA;
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, NULL ) )
+ WMFRecord_TextOut( pA->GetPoint(), aTemp );
+ }
+ break;
+
+ case META_TEXTARRAY_ACTION:
+ {
+ const MetaTextArrayAction* pA = (const MetaTextArrayAction*) pMA;
+
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pA->GetDXArray() ) )
+ WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pA->GetDXArray() );
+ }
+ break;
+
+ case META_STRETCHTEXT_ACTION:
+ {
+ const MetaStretchTextAction* pA = (const MetaStretchTextAction *) pMA;
+ String aTemp( pA->GetText(), pA->GetIndex(), pA->GetLen() );
+
+ sal_uInt16 nLen,i;
+ sal_Int32 nNormSize;
+
+ pVirDev->SetFont( aSrcFont );
+ nLen = aTemp.Len();
+ sal_Int32* pDXAry = nLen ? new sal_Int32[ nLen ] : NULL;
+ nNormSize = pVirDev->GetTextArray( aTemp, pDXAry );
+ for ( i = 0; i < ( nLen - 1 ); i++ )
+ pDXAry[ i ] = pDXAry[ i ] * (sal_Int32)pA->GetWidth() / nNormSize;
+ if ( ( nLen <= 1 ) || ( (sal_Int32)pA->GetWidth() == nNormSize ) )
+ delete[] pDXAry, pDXAry = NULL;
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+ if ( !WMFRecord_Escape_Unicode( pA->GetPoint(), aTemp, pDXAry ) )
+ WMFRecord_ExtTextOut( pA->GetPoint(), aTemp, pDXAry );
+ delete[] pDXAry;
+ }
+ break;
+
+ case META_BMP_ACTION:
+ {
+ const MetaBmpAction* pA = (const MetaBmpAction *) pMA;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetBitmap().GetSizePixel(), pA->GetBitmap() );
+ }
+ break;
+
+ case META_BMPSCALE_ACTION:
+ {
+ const MetaBmpScaleAction* pA = (const MetaBmpScaleAction*) pMA;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pA->GetBitmap() );
+ }
+ break;
+
+ case META_BMPSCALEPART_ACTION:
+ {
+ const MetaBmpScalePartAction* pA = (const MetaBmpScalePartAction*) pMA;
+ Bitmap aTmp( pA->GetBitmap() );
+
+ if( aTmp.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) ) )
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aTmp );
+ }
+ break;
+
+ case META_BMPEX_ACTION:
+ {
+ const MetaBmpExAction* pA = (const MetaBmpExAction *) pMA;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ WMFRecord_StretchDIB( pA->GetPoint(), aMsk.GetSizePixel(), aBmp, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetPoint(), aBmp.GetSizePixel(), aBmp );
+ }
+ break;
+
+ case META_BMPEXSCALE_ACTION:
+ {
+ const MetaBmpExScaleAction* pA = (const MetaBmpExScaleAction*) pMA;
+ Bitmap aBmp( pA->GetBitmapEx().GetBitmap() );
+ Bitmap aMsk( pA->GetBitmapEx().GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aMsk, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), aBmp );
+ }
+ break;
+
+ case META_BMPEXSCALEPART_ACTION:
+ {
+ const MetaBmpExScalePartAction* pA = (const MetaBmpExScalePartAction*) pMA;
+ BitmapEx aBmpEx( pA->GetBitmapEx() );
+ aBmpEx.Crop( Rectangle( pA->GetSrcPoint(), pA->GetSrcSize() ) );
+ Bitmap aBmp( aBmpEx.GetBitmap() );
+ Bitmap aMsk( aBmpEx.GetMask() );
+
+ if( !!aMsk )
+ {
+ aBmp.Replace( aMsk, COL_WHITE );
+ aMsk.Invert();
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aMsk, W_SRCPAINT );
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp, W_SRCAND );
+ }
+ else
+ WMFRecord_StretchDIB( pA->GetDestPoint(), pA->GetDestSize(), aBmp );
+ }
+ break;
+
+ case META_GRADIENT_ACTION:
+ {
+ const MetaGradientAction* pA = (const MetaGradientAction*) pMA;
+ GDIMetaFile aTmpMtf;
+
+ pVirDev->AddGradientActions( pA->GetRect(), pA->GetGradient(), aTmpMtf );
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case META_HATCH_ACTION:
+ {
+ const MetaHatchAction* pA = (const MetaHatchAction*) pMA;
+ GDIMetaFile aTmpMtf;
+
+ pVirDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case META_WALLPAPER_ACTION:
+ {
+ const MetaWallpaperAction* pA = (const MetaWallpaperAction*) pMA;
+ const Color& rColor = pA->GetWallpaper().GetColor();
+ const Color aOldLineColor( aSrcLineColor );
+ const Color aOldFillColor( aSrcFillColor );
+
+ aSrcLineColor = rColor;
+ aSrcFillColor = rColor;
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_Rectangle( pA->GetRect() );
+ aSrcLineColor = aOldLineColor;
+ aSrcFillColor = aOldFillColor;
+ }
+ break;
+
+ case META_ISECTRECTCLIPREGION_ACTION:
+ {
+ const MetaISectRectClipRegionAction* pA = (const MetaISectRectClipRegionAction*) pMA;
+ WMFRecord_IntersectClipRect( pA->GetRect() );
+ }
+ break;
+
+ case META_LINECOLOR_ACTION:
+ {
+ const MetaLineColorAction* pA = (const MetaLineColorAction*) pMA;
+
+ if( pA->IsSetting() )
+ aSrcLineColor = pA->GetColor();
+ else
+ aSrcLineColor = Color( COL_TRANSPARENT );
+ }
+ break;
+
+ case META_FILLCOLOR_ACTION:
+ {
+ const MetaFillColorAction* pA = (const MetaFillColorAction*) pMA;
+
+ if( pA->IsSetting() )
+ aSrcFillColor = pA->GetColor();
+ else
+ aSrcFillColor = Color( COL_TRANSPARENT );
+ }
+ break;
+
+ case META_TEXTCOLOR_ACTION:
+ {
+ const MetaTextColorAction* pA = (const MetaTextColorAction*) pMA;
+ aSrcTextColor = pA->GetColor();
+ }
+ break;
+
+ case META_TEXTFILLCOLOR_ACTION:
+ {
+ const MetaTextFillColorAction* pA = (const MetaTextFillColorAction*) pMA;
+ if( pA->IsSetting() )
+ aSrcFont.SetFillColor( pA->GetColor() );
+ else
+ aSrcFont.SetFillColor( Color( COL_TRANSPARENT ) );
+ }
+ break;
+
+ case META_TEXTALIGN_ACTION:
+ {
+ const MetaTextAlignAction* pA = (const MetaTextAlignAction*) pMA;
+ eSrcTextAlign = pA->GetTextAlign();
+ }
+ break;
+
+ case META_MAPMODE_ACTION:
+ {
+ const MetaMapModeAction* pA = (const MetaMapModeAction*) pMA;
+
+ if (aSrcMapMode!=pA->GetMapMode())
+ {
+ if( pA->GetMapMode().GetMapUnit() == MAP_RELATIVE )
+ {
+ MapMode aMM = pA->GetMapMode();
+ Fraction aScaleX = aMM.GetScaleX();
+ Fraction aScaleY = aMM.GetScaleY();
+
+ Point aOrigin = aSrcMapMode.GetOrigin();
+ BigInt aX( aOrigin.X() );
+ aX *= BigInt( aScaleX.GetDenominator() );
+ if( aOrigin.X() >= 0 )
+ if( aScaleX.GetNumerator() >= 0 )
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ else
+ aX -= BigInt( (aScaleX.GetNumerator()+1)/2 );
+ else
+ if( aScaleX.GetNumerator() >= 0 )
+ aX -= BigInt( (aScaleX.GetNumerator()-1)/2 );
+ else
+ aX += BigInt( aScaleX.GetNumerator()/2 );
+ aX /= BigInt( aScaleX.GetNumerator() );
+ aOrigin.X() = (long)aX + aMM.GetOrigin().X();
+ BigInt aY( aOrigin.Y() );
+ aY *= BigInt( aScaleY.GetDenominator() );
+ if( aOrigin.Y() >= 0 )
+ if( aScaleY.GetNumerator() >= 0 )
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ else
+ aY -= BigInt( (aScaleY.GetNumerator()+1)/2 );
+ else
+ if( aScaleY.GetNumerator() >= 0 )
+ aY -= BigInt( (aScaleY.GetNumerator()-1)/2 );
+ else
+ aY += BigInt( aScaleY.GetNumerator()/2 );
+ aY /= BigInt( aScaleY.GetNumerator() );
+ aOrigin.Y() = (long)aY + aMM.GetOrigin().Y();
+ aSrcMapMode.SetOrigin( aOrigin );
+
+ aScaleX *= aSrcMapMode.GetScaleX();
+ aScaleY *= aSrcMapMode.GetScaleY();
+ aSrcMapMode.SetScaleX( aScaleX );
+ aSrcMapMode.SetScaleY( aScaleY );
+ }
+ else
+ aSrcMapMode=pA->GetMapMode();
+ }
+ }
+ break;
+
+ case META_FONT_ACTION:
+ {
+ const MetaFontAction* pA = (const MetaFontAction*) pMA;
+ aSrcFont = pA->GetFont();
+
+ if ( (aSrcFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW)
+ || (aSrcFont.GetCharSet() == RTL_TEXTENCODING_UNICODE) )
+ {
+ aSrcFont.SetCharSet( RTL_TEXTENCODING_MS_1252 );
+ }
+ eSrcTextAlign = aSrcFont.GetAlign();
+ aSrcTextColor = aSrcFont.GetColor();
+ aSrcFont.SetAlign( ALIGN_BASELINE );
+ aSrcFont.SetColor( COL_WHITE );
+ }
+ break;
+
+ case META_PUSH_ACTION:
+ {
+ const MetaPushAction* pA = (const MetaPushAction*)pMA;
+
+ WMFWriterAttrStackMember* pAt = new WMFWriterAttrStackMember;
+ pAt->nFlags = pA->GetFlags();
+ pAt->aClipRegion = aSrcClipRegion;
+ pAt->aLineColor=aSrcLineColor;
+ pAt->aFillColor=aSrcFillColor;
+ pAt->eRasterOp=eSrcRasterOp;
+ pAt->aFont=aSrcFont;
+ pAt->eTextAlign=eSrcTextAlign;
+ pAt->aTextColor=aSrcTextColor;
+ pAt->aMapMode=aSrcMapMode;
+ pAt->aLineInfo=aDstLineInfo;
+ pAt->pSucc=pAttrStack;
+ pAttrStack=pAt;
+
+ SetAllAttr(); // update ( now all source attributes are equal to the destination attributes )
+ WMFRecord_SaveDC();
+
+ }
+ break;
+
+ case META_POP_ACTION:
+ {
+ WMFWriterAttrStackMember * pAt=pAttrStack;
+
+ if( pAt )
+ {
+ aDstLineInfo = pAt->aLineInfo;
+ aDstLineColor = pAt->aLineColor;
+ if ( pAt->nFlags & PUSH_LINECOLOR )
+ aSrcLineColor = pAt->aLineColor;
+ aDstFillColor = pAt->aFillColor;
+ if ( pAt->nFlags & PUSH_FILLCOLOR )
+ aSrcFillColor = pAt->aFillColor;
+ eDstROP2 = pAt->eRasterOp;
+ if ( pAt->nFlags & PUSH_RASTEROP )
+ eSrcRasterOp = pAt->eRasterOp;
+ aDstFont = pAt->aFont;
+ if ( pAt->nFlags & PUSH_FONT )
+ aSrcFont = pAt->aFont;
+ eDstTextAlign = pAt->eTextAlign;
+ if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTALIGN ) )
+ eSrcTextAlign = pAt->eTextAlign;
+ aDstTextColor = pAt->aTextColor;
+ if ( pAt->nFlags & ( PUSH_FONT | PUSH_TEXTCOLOR ) )
+ aSrcTextColor = pAt->aTextColor;
+ if ( pAt->nFlags & PUSH_MAPMODE )
+ aSrcMapMode = pAt->aMapMode;
+ aDstClipRegion = pAt->aClipRegion;
+ if ( pAt->nFlags & PUSH_CLIPREGION )
+ aSrcClipRegion = pAt->aClipRegion;
+
+ WMFRecord_RestoreDC();
+ pAttrStack = pAt->pSucc;
+ delete pAt;
+ }
+ }
+ break;
+
+ case META_EPS_ACTION :
+ {
+ const MetaEPSAction* pA = (const MetaEPSAction*)pMA;
+ const GDIMetaFile aGDIMetaFile( pA->GetSubstitute() );
+
+ size_t nCount = aGDIMetaFile.GetActionSize();
+ for ( size_t i = 0; i < nCount; i++ )
+ {
+ const MetaAction* pMetaAct = aGDIMetaFile.GetAction( i );
+ if ( pMetaAct->GetType() == META_BMPSCALE_ACTION )
+ {
+ const MetaBmpScaleAction* pBmpScaleAction = (const MetaBmpScaleAction*)pMetaAct;
+ WMFRecord_StretchDIB( pA->GetPoint(), pA->GetSize(), pBmpScaleAction->GetBitmap() );
+ break;
+ }
+ }
+ }
+ break;
+
+ case META_RASTEROP_ACTION:
+ {
+ const MetaRasterOpAction* pA = (const MetaRasterOpAction*) pMA;
+ eSrcRasterOp=pA->GetRasterOp();
+ }
+ break;
+
+ case META_TRANSPARENT_ACTION:
+ {
+ aSrcLineInfo = LineInfo();
+ SetLineAndFillAttr();
+ WMFRecord_PolyPolygon( ( (MetaTransparentAction*) pMA )->GetPolyPolygon() );
+ }
+ break;
+
+ case META_FLOATTRANSPARENT_ACTION:
+ {
+ const MetaFloatTransparentAction* pA = (const MetaFloatTransparentAction*) pMA;
+
+ 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;
+
+ aSrcLineInfo = LineInfo();
+ SetAllAttr();
+
+ 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 );
+
+ WriteRecords( aTmpMtf );
+ }
+ break;
+
+ case( META_LAYOUTMODE_ACTION ):
+ {
+ sal_uInt32 nLayoutMode = ( (MetaLayoutModeAction*) pMA )->GetLayoutMode();
+ eSrcHorTextAlign = 0; // TA_LEFT
+ if (nLayoutMode & TEXT_LAYOUT_BIDI_RTL)
+ {
+ eSrcHorTextAlign = W_TA_RIGHT | W_TA_RTLREADING;
+ }
+ if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_RIGHT)
+ eSrcHorTextAlign |= W_TA_RIGHT;
+ else if (nLayoutMode & TEXT_LAYOUT_TEXTORIGIN_LEFT)
+ eSrcHorTextAlign &= ~W_TA_RIGHT;
+ break;
+ }
+
+ // Unsupported Actions
+ case META_MASK_ACTION:
+ case META_MASKSCALE_ACTION:
+ case META_MASKSCALEPART_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaMask...Action!" );
+ }
+ break;
+
+ case META_CLIPREGION_ACTION:
+ break;
+
+ case META_ISECTREGIONCLIPREGION_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaISectRegionClipRegionAction!" );
+ }
+ break;
+
+ case META_MOVECLIPREGION_ACTION:
+ {
+ OSL_FAIL( "Unsupported action: MetaMoveClipRegionAction!" );
+ }
+ break;
+
+ default:
+ {
+ OSL_FAIL( "Unsupported meta action!" );
+ }
+ break;
+ }
+
+ nWrittenActions++;
+ MayCallback();
+
+ if (pWMF->GetError())
+ bStatus=sal_False;
+
+ if(bStatus==sal_False)
+ break;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteHeader( const GDIMetaFile &, sal_Bool bPlaceable )
+{
+ if( bPlaceable )
+ {
+ sal_uInt16 nCheckSum, nValue;
+ Size aSize( pVirDev->LogicToLogic(Size(1,1),MapMode(MAP_INCH), aTargetMapMode) );
+ sal_uInt16 nUnitsPerInch = (sal_uInt16) ( ( aSize.Width() + aSize.Height() ) >> 1 );
+
+ nCheckSum=0;
+ nValue=0xcdd7; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x9ac6; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=(sal_uInt16) aTargetSize.Width(); nCheckSum^=nValue; *pWMF << nValue;
+ nValue=(sal_uInt16) aTargetSize.Height(); nCheckSum^=nValue; *pWMF << nValue;
+ nValue=nUnitsPerInch; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ nValue=0x0000; nCheckSum^=nValue; *pWMF << nValue;
+ *pWMF << nCheckSum;
+ }
+
+ nMetafileHeaderPos=pWMF->Tell();
+ *pWMF << (sal_uInt16)0x0001 // Typ: Datei
+ << (sal_uInt16)0x0009 // Headerlaenge in Worten
+ << (sal_uInt16)0x0300 // Version als BCD-Zahl
+ << (sal_uInt32) 0x00000000 // Dateilaenge (ohne 1. Header), wird spaeter durch UpdateHeader() berichtigt
+ << (sal_uInt16)MAXOBJECTHANDLES // Maximalezahl der gleichzeitigen Objekte
+ << (sal_uInt32) 0x00000000 // Maximale Record-laenge, wird spaeter durch UpdateHeader() berichtigt
+ << (sal_uInt16)0x0000; // Reserved
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::UpdateHeader()
+{
+ sal_uLong nPos;
+ sal_uInt32 nFileSize;
+
+ nPos=pWMF->Tell(); // Endposition = Gesammtgroesse der Datei
+ nFileSize=nPos-nMetafileHeaderPos; // Groesse des 1. Headers abziehen
+ if ((nFileSize&1)!=0) { // ggf. auf ganze Worte aufrunden
+ *pWMF << (sal_uInt8)0;
+ nPos++;
+ nFileSize++;
+ }
+ nFileSize>>=1; // In Anzahl Worte umrechnen
+ pWMF->Seek(nMetafileHeaderPos+6); // Zum Dateigroessen-Eintrag im zweiten Header
+ *pWMF << nFileSize; // Dateigroesse berichtigen
+ pWMF->SeekRel(2); // Zum Max-Record-Laenge-Eintrag im zweiten Header
+ *pWMF << nMaxRecordSize; // und berichtigen
+ pWMF->Seek(nPos);
+}
+
+// ------------------------------------------------------------------------
+
+sal_Bool WMFWriter::WriteWMF( const GDIMetaFile& rMTF, SvStream& rTargetStream,
+ FilterConfigItem* pFConfigItem, sal_Bool bPlaceable )
+{
+ WMFWriterAttrStackMember * pAt;
+
+ bEmbedEMF = sal_True;
+ bStatus=sal_True;
+ pConvert = 0;
+ pVirDev = new VirtualDevice;
+
+ pFilterConfigItem = pFConfigItem;
+ if ( pFilterConfigItem )
+ {
+ xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
+ if ( xStatusIndicator.is() )
+ {
+ rtl::OUString aMsg;
+ xStatusIndicator->start( aMsg, 100 );
+ }
+ }
+ nLastPercent=0;
+
+ pWMF=&rTargetStream;
+ pWMF->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+
+ nMaxRecordSize=0;
+
+ aSrcMapMode=rMTF.GetPrefMapMode();
+
+ if( bPlaceable )
+ {
+ aTargetMapMode = aSrcMapMode;
+ aTargetSize = rMTF.GetPrefSize();
+ nTargetDivisor = CalcSaveTargetMapMode(aTargetMapMode, aTargetSize);
+ aTargetSize.Width() /= nTargetDivisor;
+ aTargetSize.Height() /= nTargetDivisor;
+ }
+ else
+ {
+ aTargetMapMode = MapMode( MAP_INCH );
+
+ const long nUnit = pVirDev->LogicToPixel( Size( 1, 1 ), aTargetMapMode ).Width();
+ const Fraction aFrac( 1, nUnit );
+
+ aTargetMapMode.SetScaleX( aFrac );
+ aTargetMapMode.SetScaleY( aFrac );
+ aTargetSize = pVirDev->LogicToLogic( rMTF.GetPrefSize(), aSrcMapMode, aTargetMapMode );
+ }
+
+ pVirDev->SetMapMode( aTargetMapMode );
+
+ pAttrStack=NULL;
+
+ for (sal_uInt16 i=0; i<MAXOBJECTHANDLES; i++)
+ bHandleAllocated[i]=sal_False;
+
+ nDstPenHandle=0xffff;
+ nDstFontHandle=0xffff;
+ nDstBrushHandle=0xffff;
+
+ nNumberOfActions=0;
+ nNumberOfBitmaps=0;
+ nWrittenActions=0;
+ nWrittenBitmaps=0;
+ nActBitmapPercent=0;
+
+ CountActionsAndBitmaps(rMTF);
+
+ WriteHeader(rMTF,bPlaceable);
+ if( bEmbedEMF )
+ WriteEmbeddedEMF( rMTF );
+ WMFRecord_SetWindowOrg(Point(0,0));
+ WMFRecord_SetWindowExt(rMTF.GetPrefSize());
+ WMFRecord_SetBkMode( sal_True );
+
+ eDstROP2 = eSrcRasterOp = ROP_OVERPAINT;
+ WMFRecord_SetROP2(eDstROP2);
+
+ aDstLineInfo = LineInfo();
+ aDstLineColor = aSrcLineColor = Color( COL_BLACK );
+ CreateSelectDeletePen( aDstLineColor, aDstLineInfo );
+
+ aDstFillColor = aSrcFillColor = Color( COL_WHITE );
+ CreateSelectDeleteBrush( aDstFillColor );
+
+ aDstClipRegion = aSrcClipRegion = Region();
+ bDstIsClipping = bSrcIsClipping = sal_False;
+
+ Font aFont;
+ aFont.SetCharSet( GetExtendedTextEncoding( RTL_TEXTENCODING_MS_1252 ) );
+ aFont.SetColor( Color( COL_WHITE ) );
+ aFont.SetAlign( ALIGN_BASELINE );
+ aDstFont = aSrcFont = aFont;
+ CreateSelectDeleteFont(aDstFont);
+
+ eDstTextAlign = eSrcTextAlign = ALIGN_BASELINE;
+ eDstHorTextAlign = eSrcHorTextAlign = W_TA_LEFT;
+ WMFRecord_SetTextAlign( eDstTextAlign, eDstHorTextAlign );
+
+ aDstTextColor = aSrcTextColor = Color( COL_WHITE );
+ WMFRecord_SetTextColor(aDstTextColor);
+
+ // Write records
+ WriteRecords(rMTF);
+
+ WMFRecord_EndOfFile();
+ UpdateHeader();
+
+ while(pAttrStack)
+ {
+ pAt=pAttrStack;
+ pAttrStack=pAt->pSucc;
+ delete pAt;
+ }
+
+ delete pVirDev;
+ delete pConvert;
+
+ if ( xStatusIndicator.is() )
+ xStatusIndicator->end();
+
+ return bStatus;
+}
+
+// ------------------------------------------------------------------------
+
+sal_uInt16 WMFWriter::CalcSaveTargetMapMode(MapMode& rMapMode,
+ const Size& rPrefSize)
+{
+ Fraction aDivFrac(2, 1);
+ sal_uInt16 nDivisor = 1;
+
+ Size aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
+
+ while( nDivisor <= 64 && (aSize.Width() > 32767 || aSize.Height() > 32767) )
+ {
+ Fraction aFrac = rMapMode.GetScaleX();
+
+ aFrac *= aDivFrac;
+ rMapMode.SetScaleX(aFrac);
+ aFrac = rMapMode.GetScaleY();
+ aFrac *= aDivFrac;
+ rMapMode.SetScaleY(aFrac);
+ nDivisor <<= 1;
+ aSize = pVirDev->LogicToLogic( rPrefSize, aSrcMapMode, rMapMode );
+ }
+
+ return nDivisor;
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteEmbeddedEMF( const GDIMetaFile& rMTF )
+{
+ SvMemoryStream aStream;
+ EMFWriter aEMFWriter(aStream);
+
+ if( aEMFWriter.WriteEMF( rMTF ) )
+ {
+ sal_Size nTotalSize = aStream.Tell();
+ if( nTotalSize > SAL_MAX_UINT32 )
+ return;
+ aStream.Seek( 0 );
+ sal_uInt32 nRemainingSize = static_cast< sal_uInt32 >( nTotalSize );
+ sal_uInt32 nRecCounts = ( (nTotalSize - 1) / 0x2000 ) + 1;
+ sal_uInt16 nCheckSum = 0, nWord;
+
+ sal_uInt32 nPos = 0;
+
+ while( nPos + 1 < nTotalSize )
+ {
+ aStream >> nWord;
+ nCheckSum ^= nWord;
+ nPos += 2;
+ }
+
+ nCheckSum = static_cast< sal_uInt16 >( nCheckSum * -1 );
+
+ aStream.Seek( 0 );
+ while( nRemainingSize > 0 )
+ {
+ sal_uInt32 nCurSize;
+ if( nRemainingSize > 0x2000 )
+ {
+ nCurSize = 0x2000;
+ nRemainingSize -= 0x2000;
+ }
+ else
+ {
+ nCurSize = nRemainingSize;
+ nRemainingSize = 0;
+ }
+ WriteEMFRecord( aStream,
+ nCurSize,
+ nRemainingSize,
+ nTotalSize,
+ nRecCounts,
+ nCheckSum );
+ nCheckSum = 0;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+void WMFWriter::WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize, sal_uInt32 nRemainingSize,
+ sal_uInt32 nTotalSize, sal_uInt32 nRecCounts, sal_uInt16 nCheckSum )
+{
+ // according to http://msdn.microsoft.com/en-us/library/dd366152%28PROT.13%29.aspx
+ WriteRecordHeader( 0, W_META_ESCAPE );
+ *pWMF << (sal_uInt16)W_MFCOMMENT // same as META_ESCAPE_ENHANCED_METAFILE
+ << (sal_uInt16)( nCurSize + 34 ) // we will always have a 34 byte escape header:
+ << (sal_uInt32) 0x43464D57 // WMFC
+ << (sal_uInt32) 0x00000001 // Comment type
+ << (sal_uInt32) 0x00010000 // version
+ << nCheckSum // check sum
+ << (sal_uInt32) 0 // flags = 0
+ << nRecCounts // total number of records
+ << nCurSize // size of this record's data
+ << nRemainingSize // remaining size of data in following records, missing in MSDN documentation
+ << nTotalSize; // total size of EMF stream
+
+ pWMF->Write( static_cast< const sal_Char* >( rStream.GetData() ) + rStream.Tell(), nCurSize );
+ rStream.SeekRel( nCurSize );
+ UpdateRecordHeader();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/filter/wmf/wmfwr.hxx b/vcl/source/filter/wmf/wmfwr.hxx
new file mode 100644
index 000000000000..f71abaa8ea93
--- /dev/null
+++ b/vcl/source/filter/wmf/wmfwr.hxx
@@ -0,0 +1,220 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _WMFWR_HXX
+#define _WMFWR_HXX
+
+#include <vcl/metaact.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/virdev.hxx>
+#include <svtools/fltcall.hxx>
+
+// -----------------------------------------------------------------------------
+
+#define MAXOBJECTHANDLES 16
+
+// -----------------------------------------------------------------------------
+
+struct WMFWriterAttrStackMember
+{
+ struct WMFWriterAttrStackMember * pSucc;
+ Color aLineColor;
+ Color aFillColor;
+ Color aTextColor;
+ LineInfo aLineInfo;
+ TextAlign eTextAlign;
+ RasterOp eRasterOp;
+ Font aFont;
+ MapMode aMapMode;
+ Region aClipRegion;
+ sal_uInt16 nFlags;
+};
+
+// -------------
+// - WMFWriter -
+// -------------
+
+class StarSymbolToMSMultiFont;
+class LineInfo;
+namespace basegfx { class B2DPolygon; }
+
+class WMFWriter
+{
+private:
+
+ sal_Bool bStatus;
+
+ sal_uLong nLastPercent; // Mit welcher Zahl pCallback zuletzt aufgerufen wurde.
+ FilterConfigItem* pFilterConfigItem;
+
+ com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;
+
+ SvStream* pWMF;
+ VirtualDevice* pVirDev;
+ StarSymbolToMSMultiFont *pConvert;
+ MapMode aTargetMapMode;
+ Size aTargetSize;
+ sal_uInt16 nTargetDivisor;
+
+ sal_uLong nMetafileHeaderPos;
+ sal_uInt32 nMaxRecordSize; // in Worten
+ sal_uLong nActRecordPos;
+
+ // Aktuelle Attribute im Quell-Metafile:
+ Color aSrcLineColor;
+ Color aSrcFillColor;
+ Color aSrcTextColor;
+ LineInfo aSrcLineInfo;
+ RasterOp eSrcRasterOp;
+ FontAlign eSrcTextAlign;
+ Font aSrcFont;
+ MapMode aSrcMapMode;
+ sal_Bool bSrcIsClipping;
+ Region aSrcClipRegion;
+ WMFWriterAttrStackMember * pAttrStack;
+
+ sal_uInt32 eSrcHorTextAlign;
+
+ // Aktuelle Attribute im Ziel-Metafile:
+ Color aDstLineColor;
+ Color aDstFillColor;
+ Color aDstTextColor;
+ LineInfo aDstLineInfo;
+ RasterOp eDstROP2;
+ FontAlign eDstTextAlign;
+ Font aDstFont;
+
+ sal_uInt32 eDstHorTextAlign;
+
+ sal_Bool bDstIsClipping; // ???: derzeit unberuecksichtigt
+ Region aDstClipRegion; // ???: derzeit unberuecksichtigt
+ sal_Bool bHandleAllocated[MAXOBJECTHANDLES]; // Welche Handles vergeben sind
+ sal_uInt16 nDstPenHandle,nDstFontHandle,nDstBrushHandle; // Welche Handles die jeweiligen
+ // Selected-Objects besitzen
+ // 0xffff = keines:
+
+ // Damit nicht bei jeder Operation alle Attribute verglichen werden muessen:
+
+ sal_uLong nNumberOfActions; // Anzahl der Actions im GDIMetafile
+ sal_uLong nNumberOfBitmaps; // Anzahl der Bitmaps
+ sal_uLong nWrittenActions; // Anzahl der bereits verarbeiteten Actions beim Schreiben der Orders
+ sal_uLong nWrittenBitmaps; // Anzahl der bereits geschriebenen Bitmaps
+ sal_uLong nActBitmapPercent; // Wieviel Prozent die naechste Bitmap schon geschrieben ist.
+
+ sal_Bool bEmbedEMF; // optionally embedd EMF data into WMF
+
+ void MayCallback();
+ // Berechnet anhand der obigen 5 Parameter eine Prozentzahl
+ // und macht dann ggf. einen Callback. Setzt bStatus auf FALSE wenn User abbrechen
+ // moechte.
+
+ void CountActionsAndBitmaps(const GDIMetaFile & rMTF);
+ // Zaehlt die Bitmaps und Actions (nNumberOfActions und nNumberOfBitmaps muessen
+ // zu Anfang auf 0 gesetzt werden, weil diese Methode rekursiv ist)
+
+ void WritePointXY(const Point & rPoint);
+ void WritePointYX(const Point & rPoint);
+ sal_Int32 ScaleWidth( sal_Int32 nDX );
+ void WriteSize(const Size & rSize);
+ void WriteHeightWidth(const Size & rSize);
+ void WriteRectangle(const Rectangle & rRect);
+ void WriteColor(const Color & rColor);
+
+ void WriteRecordHeader(sal_uInt32 nSizeWords, sal_uInt16 nType);
+ // nSizeWords ist die Groesse des gesammten Records in Anzahl Worte.
+ // Wenn nSizeWords unbekannt ist, dann 0 einsetzen (siehe UpdateRecordHeader()).
+
+ void UpdateRecordHeader();
+ // berichtig die Groesse des Records nach dem Schreiben der Parameter, wenn
+ // nSizeWords bei Aufruf von WriteRecordHeader(..) unbekannt war.
+ // fuegt ggf. noch ein BYTE 0 ein damit Anzahl Bytes immer gerade.
+
+ void WMFRecord_Arc(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_Chord(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_CreateBrushIndirect(const Color& rColor);
+ void WMFRecord_CreateFontIndirect(const Font & rFont);
+ void WMFRecord_CreatePenIndirect(const Color& rColor, const LineInfo& rLineInfo );
+ void WMFRecord_DeleteObject(sal_uInt16 nObjectHandle);
+ void WMFRecord_Ellipse(const Rectangle & rRect);
+ void WMFRecord_Escape( sal_uInt32 nEsc, sal_uInt32 nLen, const sal_Int8* pData );
+ sal_Bool WMFRecord_Escape_Unicode( const Point& rPoint, const String& rStr, const sal_Int32 * pDXAry );
+ void WMFRecord_ExtTextOut(const Point & rPoint, const String & rString, const sal_Int32 * pDXAry);
+
+ void TrueExtTextOut(const Point & rPoint, const String & rString,
+ const rtl::OString& rByteString, const sal_Int32 * pDXAry);
+ void TrueTextOut(const Point & rPoint, const rtl::OString& rString);
+ void WMFRecord_LineTo(const Point & rPoint);
+ void WMFRecord_MoveTo(const Point & rPoint);
+ void WMFRecord_Pie(const Rectangle & rRect, const Point & rStartPt, const Point & rEndPt);
+ void WMFRecord_Polygon(const Polygon & rPoly);
+ void WMFRecord_PolyLine(const Polygon & rPoly);
+ void WMFRecord_PolyPolygon(const PolyPolygon & rPolyPoly);
+ void WMFRecord_Rectangle(const Rectangle & rRect);
+ void WMFRecord_RestoreDC();
+ void WMFRecord_RoundRect(const Rectangle & rRect, long nHorzRound, long nVertRound);
+ void WMFRecord_SaveDC();
+ void WMFRecord_SelectObject(sal_uInt16 nObjectHandle);
+ void WMFRecord_SetBkMode(sal_Bool bTransparent);
+ void WMFRecord_SetStretchBltMode();
+ void WMFRecord_SetPixel(const Point & rPoint, const Color & rColor);
+ void WMFRecord_SetROP2(RasterOp eROP);
+ void WMFRecord_SetTextAlign(FontAlign eFontAlign, sal_uInt32 eHorTextAlign);
+ void WMFRecord_SetTextColor(const Color & rColor);
+ void WMFRecord_SetWindowExt(const Size & rSize);
+ void WMFRecord_SetWindowOrg(const Point & rPoint);
+ void WMFRecord_StretchDIB(const Point & rPoint, const Size & rSize, const Bitmap & rBitmap, sal_uInt32 nROP = 0UL );
+ void WMFRecord_TextOut(const Point & rPoint, const String & rString);
+ void WMFRecord_EndOfFile();
+ void WMFRecord_IntersectClipRect( const Rectangle& rRect);
+
+ sal_uInt16 AllocHandle();
+ void FreeHandle(sal_uInt16 nObjectHandle);
+ void CreateSelectDeletePen( const Color& rColor, const LineInfo& rLineInfo );
+ void CreateSelectDeleteFont(const Font & rFont);
+ void CreateSelectDeleteBrush(const Color& rColor);
+
+ void SetLineAndFillAttr();
+ void SetAllAttr();
+
+ void HandleLineInfoPolyPolygons(const LineInfo& rInfo, const basegfx::B2DPolygon& rLinePolygon);
+ void WriteRecords(const GDIMetaFile & rMTF);
+
+ void WriteHeader(const GDIMetaFile & rMTF, sal_Bool bPlaceable);
+ void UpdateHeader();
+
+ void WriteEmbeddedEMF( const GDIMetaFile& rMTF );
+ void WriteEMFRecord( SvMemoryStream& rStream, sal_uInt32 nCurSize,
+ sal_uInt32 nRemainingSize,
+ sal_uInt32 nTotalSize,
+ sal_uInt32 nRecCounts,
+ sal_uInt16 nCheckSum );
+
+ sal_uInt16 CalcSaveTargetMapMode(MapMode& rMapMode, const Size& rPrefSize);
+
+public:
+
+ WMFWriter() {}
+
+ sal_Bool WriteWMF(const GDIMetaFile & rMTF, SvStream & rTargetStream, FilterConfigItem* pFilterConfigItem, sal_Bool bPlaceable=sal_True);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */