summaryrefslogtreecommitdiffstats
path: root/filters/karbon
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /filters/karbon
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'filters/karbon')
-rw-r--r--filters/karbon/Makefile.am2
-rw-r--r--filters/karbon/ai/Makefile.am44
-rw-r--r--filters/karbon/ai/ai3handler.cc74
-rw-r--r--filters/karbon/ai/ai3handler.h39
-rw-r--r--filters/karbon/ai/ai88handler.cc564
-rw-r--r--filters/karbon/ai/ai88handler.h56
-rw-r--r--filters/karbon/ai/aicolor.cc100
-rw-r--r--filters/karbon/ai/aicolor.h57
-rw-r--r--filters/karbon/ai/aielement.cc804
-rw-r--r--filters/karbon/ai/aielement.h151
-rw-r--r--filters/karbon/ai/aiimport.cc101
-rw-r--r--filters/karbon/ai/aiimport.h47
-rw-r--r--filters/karbon/ai/ailexer.cc514
-rw-r--r--filters/karbon/ai/ailexer.h123
-rw-r--r--filters/karbon/ai/aiparserbase.cc1337
-rw-r--r--filters/karbon/ai/aiparserbase.h440
-rw-r--r--filters/karbon/ai/karbon_ai_import.desktop67
-rw-r--r--filters/karbon/ai/karbonaiparserbase.cc637
-rw-r--r--filters/karbon/ai/karbonaiparserbase.h202
-rw-r--r--filters/karbon/applixgraphics/Makefile.am20
-rw-r--r--filters/karbon/applixgraphics/applixgraphicimport.cc832
-rw-r--r--filters/karbon/applixgraphics/applixgraphicimport.h71
-rw-r--r--filters/karbon/applixgraphics/kontour_applixgraphic_import.desktop69
-rw-r--r--filters/karbon/applixgraphics/status.html175
-rw-r--r--filters/karbon/eps/Makefile.am37
-rw-r--r--filters/karbon/eps/epsexport.cc481
-rw-r--r--filters/karbon/eps/epsexport.h71
-rw-r--r--filters/karbon/eps/epsexportdlg.cc65
-rw-r--r--filters/karbon/eps/epsexportdlg.h44
-rw-r--r--filters/karbon/eps/epsimport.cc117
-rw-r--r--filters/karbon/eps/epsimport.h42
-rw-r--r--filters/karbon/eps/karbon_eps_export.desktop66
-rw-r--r--filters/karbon/eps/karbon_eps_import.desktop66
-rw-r--r--filters/karbon/eps/karbon_ps_import.desktop66
-rw-r--r--filters/karbon/eps/pscommentlexer.cc324
-rw-r--r--filters/karbon/eps/pscommentlexer.h112
-rw-r--r--filters/karbon/kontour/Makefile.am27
-rw-r--r--filters/karbon/kontour/karbon_kontour_import.desktop66
-rw-r--r--filters/karbon/kontour/kontourimport.cpp323
-rw-r--r--filters/karbon/kontour/kontourimport.h48
-rw-r--r--filters/karbon/msod/Makefile.am18
-rw-r--r--filters/karbon/msod/karbon_msod_import.desktop61
-rw-r--r--filters/karbon/msod/msod.cc1340
-rw-r--r--filters/karbon/msod/msod.h307
-rw-r--r--filters/karbon/msod/msodimport.cc313
-rw-r--r--filters/karbon/msod/msodimport.h87
-rw-r--r--filters/karbon/msod/status.html153
-rw-r--r--filters/karbon/oodraw/Makefile.am24
-rw-r--r--filters/karbon/oodraw/karbon_oodraw_import.desktop63
-rw-r--r--filters/karbon/oodraw/oodrawimport.cc757
-rw-r--r--filters/karbon/oodraw/oodrawimport.h78
-rw-r--r--filters/karbon/png/Makefile.am27
-rw-r--r--filters/karbon/png/karbon_png_export.desktop67
-rw-r--r--filters/karbon/png/pngexport.cc96
-rw-r--r--filters/karbon/png/pngexport.h39
-rw-r--r--filters/karbon/svg/Makefile.am34
-rw-r--r--filters/karbon/svg/TODO8
-rw-r--r--filters/karbon/svg/color.h306
-rw-r--r--filters/karbon/svg/karbon_svg_export.desktop67
-rw-r--r--filters/karbon/svg/karbon_svg_import.desktop64
-rw-r--r--filters/karbon/svg/svgexport.cc512
-rw-r--r--filters/karbon/svg/svgexport.h88
-rw-r--r--filters/karbon/svg/svggraphiccontext.h48
-rw-r--r--filters/karbon/svg/svgimport.cc1389
-rw-r--r--filters/karbon/svg/svgimport.h102
-rw-r--r--filters/karbon/wmf/Makefile.am27
-rw-r--r--filters/karbon/wmf/karbon_wmf_export.desktop63
-rw-r--r--filters/karbon/wmf/karbon_wmf_import.desktop66
-rw-r--r--filters/karbon/wmf/wmfexport.cc263
-rw-r--r--filters/karbon/wmf/wmfexport.h71
-rw-r--r--filters/karbon/wmf/wmfimport.cc78
-rw-r--r--filters/karbon/wmf/wmfimport.h42
-rw-r--r--filters/karbon/wmf/wmfimportparser.cc371
-rw-r--r--filters/karbon/wmf/wmfimportparser.h141
-rw-r--r--filters/karbon/xaml/Makefile.am35
-rw-r--r--filters/karbon/xaml/color.h306
-rw-r--r--filters/karbon/xaml/karbon_xaml_export.desktop54
-rw-r--r--filters/karbon/xaml/karbon_xaml_import.desktop53
-rw-r--r--filters/karbon/xaml/xamlexport.cc371
-rw-r--r--filters/karbon/xaml/xamlexport.h76
-rw-r--r--filters/karbon/xaml/xamlgraphiccontext.h46
-rw-r--r--filters/karbon/xaml/xamlimport.cc1042
-rw-r--r--filters/karbon/xaml/xamlimport.h91
-rw-r--r--filters/karbon/xcf/Makefile.am27
-rw-r--r--filters/karbon/xcf/karbon_xcf_export.desktop65
-rw-r--r--filters/karbon/xcf/xcfexport.cc458
-rw-r--r--filters/karbon/xcf/xcfexport.h97
-rw-r--r--filters/karbon/xfig/karbon_xfig_import.desktop61
-rw-r--r--filters/karbon/xfig/status.html157
-rw-r--r--filters/karbon/xfig/xfigimport.cc760
-rw-r--r--filters/karbon/xfig/xfigimport.h94
-rw-r--r--filters/karbon/xfig/xfigimport_factory.cc67
-rw-r--r--filters/karbon/xfig/xfigimport_factory.h46
93 files changed, 19557 insertions, 0 deletions
diff --git a/filters/karbon/Makefile.am b/filters/karbon/Makefile.am
new file mode 100644
index 00000000..f6202386
--- /dev/null
+++ b/filters/karbon/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = eps ai svg png wmf kontour xcf msod oodraw
+
diff --git a/filters/karbon/ai/Makefile.am b/filters/karbon/ai/Makefile.am
new file mode 100644
index 00000000..761feaff
--- /dev/null
+++ b/filters/karbon/ai/Makefile.am
@@ -0,0 +1,44 @@
+kde_module_LTLIBRARIES = libkarbonaiimport.la
+
+libkarbonaiimport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+libkarbonaiimport_la_LDFLAGS = \
+ $(all_libraries) \
+ $(KDE_RPATH) \
+ -module -avoid-version -no-undefined
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ $(all_includes)
+
+service_DATA = karbon_ai_import.desktop
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ aicolor.h \
+ aielement.h \
+ aiimport.h \
+ ailexer.h \
+ aiparserbase.h \
+ ai88handler.h \
+ ai3handler.h \
+ karbonaiparserbase.h
+
+libkarbonaiimport_la_SOURCES = \
+ aicolor.cc \
+ aielement.cc \
+ aiimport.cc \
+ ailexer.cc \
+ aiparserbase.cc \
+ ai88handler.cc \
+ ai3handler.cc \
+ karbonaiparserbase.cc
+
+libkarbonaiimport_la_METASOURCES = \
+ AUTO
+
diff --git a/filters/karbon/ai/ai3handler.cc b/filters/karbon/ai/ai3handler.cc
new file mode 100644
index 00000000..ae0252a3
--- /dev/null
+++ b/filters/karbon/ai/ai3handler.cc
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "ai3handler.h"
+
+AI3Handler::AI3Handler(AIParserBase *delegate){
+ m_delegate = delegate;
+}
+AI3Handler::~AI3Handler(){
+}
+
+bool AI3Handler::handleAIOperation (AIOperation op) {
+// PathElement pathElement;
+// double fval;
+ int ival;
+
+ switch (op) {
+ case AIO_SetWindingOrder :
+ ival = m_delegate->getIntValue();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotWindingOrder (ival);
+ return true;
+ break;
+ case AIO_BeginGroupNoClip :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotBeginGroup (false);
+ return true;
+ break;
+ case AIO_EndGroupNoClip :
+ if (m_delegate->m_debug) qDebug ("got end group noclip");
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotEndGroup (false);
+ if (m_delegate->m_debug) qDebug ("/got end group noclip");
+ return true;
+ break;
+ case AIO_BeginCombination :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotBeginCombination ();
+ return true;
+ break;
+ case AIO_EndCombination :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotEndCombination ();
+ return true;
+ break;
+ case AIO_BeginGroupClip :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotBeginGroup (true);
+ return true;
+ break;
+ case AIO_EndGroupClip :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotEndGroup (true);
+ return true;
+ break;
+ case AIO_SetFillMode :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotFillMode((FillMode) m_delegate->getIntValue());
+ return true;
+ break;
+ default :
+ return false;
+ }
+ return false;
+}
+
diff --git a/filters/karbon/ai/ai3handler.h b/filters/karbon/ai/ai3handler.h
new file mode 100644
index 00000000..27f23cec
--- /dev/null
+++ b/filters/karbon/ai/ai3handler.h
@@ -0,0 +1,39 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AI3HANDLER_H
+#define AI3HANDLER_H
+
+#include "aiparserbase.h"
+
+/**
+ *@author Dirk Schoenberger
+ */
+
+class AI3Handler {
+private:
+ AIParserBase *m_delegate;
+public:
+ AI3Handler(AIParserBase *delegate);
+ ~AI3Handler();
+
+ bool handleAIOperation (AIOperation op);
+};
+
+#endif
diff --git a/filters/karbon/ai/ai88handler.cc b/filters/karbon/ai/ai88handler.cc
new file mode 100644
index 00000000..f3cf53a7
--- /dev/null
+++ b/filters/karbon/ai/ai88handler.cc
@@ -0,0 +1,564 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kglobal.h>
+#include "ai88handler.h"
+
+AI88Handler::AI88Handler(AIParserBase *delegate){
+ m_delegate = delegate;
+}
+AI88Handler::~AI88Handler(){
+}
+
+bool AI88Handler::handleAIOperation (AIOperation op) {
+ PathElement pathElement;
+ double fval;
+ int ival;
+
+ switch (op) {
+ case AIO_SetFillColorCMYK :
+ _handleSetFillColorCMYK();
+ return true;
+ break;
+ case AIO_SetStrokeColorCMYK :
+ _handleSetStrokeColorCMYK();
+ return true;
+ break;
+ case AIO_SetFillColorGray :
+ _handleSetFillColorGray();
+ return true;
+ break;
+ case AIO_SetStrokeColorGray :
+ _handleSetStrokeColorGray();
+ return true;
+ break;
+ case AIO_SetFillColorCustom :
+ _handleSetFillColorCustom();
+ return true;
+ break;
+ case AIO_SetStrokeColorCustom :
+ _handleSetStrokeColorCustom();
+ return true;
+ break;
+ case AIO_SetFillPattern :
+ _handleSetFillPattern();
+ return true;
+ break;
+ case AIO_SetStrokePattern :
+ _handleSetStrokePattern();
+ return true;
+ break;
+ case AIO_SetFillOverprinting :
+ if (m_delegate->m_miscGStateHandler) m_delegate->m_miscGStateHandler->gotFillOverprinting (m_delegate->getBoolValue());
+ return true;
+ break;
+ case AIO_SetStrokeOverprinting :
+ if (m_delegate->m_miscGStateHandler) m_delegate->m_miscGStateHandler->gotStrokeOverprinting (m_delegate->getBoolValue());
+ return true;
+ break;
+ case AIO_LockElement :
+ if (m_delegate->m_miscGStateHandler) m_delegate->m_miscGStateHandler->gotLockNextObject (m_delegate->getBoolValue());
+ return true;
+ break;
+ case AIO_SetFlatness :
+ fval = m_delegate->getDoubleValue();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotFlatness (fval);
+ return true;
+ break;
+ case AIO_SetLineCap :
+ ival = m_delegate->getIntValue();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotLineCaps (ival);
+ return true;
+ break;
+ case AIO_SetLineJoin :
+ ival = m_delegate->getIntValue();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotLineJoin (ival);
+ return true;
+ break;
+ case AIO_SetLineWidth :
+ fval = kMax(0.2, m_delegate->getDoubleValue()); // Use thinnest pen stroke possible for 0 (Rob)
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotLineWidth (fval);
+ return true;
+ break;
+ case AIO_SetMiterLimit :
+ fval = m_delegate->getDoubleValue();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotMiterLimit (fval);
+ return true;
+ break;
+ case AIO_SetDash :
+ _handleSetDash();
+ return true;
+ break;
+ case AIO_BeginGroupClip :
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotBeginGroup (true);
+ return true;
+ break;
+ case AIO_EndGroupClip :
+ if (m_delegate->m_debug) qDebug ("got end group clip");
+ if (m_delegate->m_structureHandler) m_delegate->m_structureHandler->gotEndGroup (true);
+ if (m_delegate->m_debug) qDebug ("/got end group clip");
+ return true;
+
+ break;
+ case AIO_MoveTo :
+ pathElement.petype = PET_MoveTo;
+ pathElement.pttype = PT_Corner;
+ pathElement.pevalue.pointdata.y = m_delegate->getDoubleValue();
+ pathElement.pevalue.pointdata.x = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_LineToCorner :
+ pathElement.petype = PET_LineTo;
+ pathElement.pttype = PT_Corner;
+ pathElement.pevalue.pointdata.y = m_delegate->getDoubleValue();
+ pathElement.pevalue.pointdata.x = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_LineToSmooth :
+ pathElement.petype = PET_LineTo;
+ pathElement.pttype = PT_Smooth;
+ pathElement.pevalue.pointdata.y = m_delegate->getDoubleValue();
+ pathElement.pevalue.pointdata.x = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToCorner :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Corner;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y1 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x1 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToSmooth :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Smooth;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y1 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x1 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToOmitC1Corner :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Corner;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x2 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToOmitC1Smooth :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Smooth;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y2 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x2 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToOmitC2Corner :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Corner;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y1 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x1 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+ case AIO_CurveToOmitC2Smooth :
+ pathElement.petype = PET_CurveTo;
+ pathElement.pttype = PT_Smooth;
+ pathElement.pevalue.bezierdata.y3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x3 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.y1 = m_delegate->getDoubleValue();
+ pathElement.pevalue.bezierdata.x1 = m_delegate->getDoubleValue();
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotPathElement (pathElement);
+ return true;
+ break;
+
+ case AIO_PathIgnoreReset :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotIgnorePath(false, true);
+ return true;
+ break;
+ case AIO_PathIgnoreResetClose :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotIgnorePath(true, true);
+ return true;
+ break;
+ case AIO_PathIgnoreNoReset :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotIgnorePath(false, false);
+ return true;
+ break;
+ case AIO_PathIgnoreNoResetClose :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotIgnorePath(true, false);
+ return true;
+ break;
+ case AIO_PathClipPath :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotClipPath(false);
+ return true;
+ break;
+ case AIO_PathFillNonZero :
+ if (m_delegate->m_pathHandler)
+ {
+ m_delegate->m_pathHandler->gotFillMode (FM_NonZero);
+ m_delegate->m_pathHandler->gotFillPath(false, true);
+ }
+ return true;
+ break;
+ case AIO_PathFillNonZeroClose :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotFillPath(true, true);
+ return true;
+ break;
+ case AIO_PathFillNoReset :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotFillPath(false, false);
+ return true;
+ break;
+ case AIO_PathFillNoResetClose :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotFillPath(true, false);
+ return true;
+ break;
+ case AIO_PathStroke :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotStrokePath(false);
+ return true;
+ break;
+ case AIO_PathStrokeClose :
+ if (m_delegate->m_pathHandler) m_delegate->m_pathHandler->gotStrokePath(true);
+ return true;
+ break;
+ case AIO_PatternDefinition :
+ _handlePatternDefinition();
+ return true;
+ break;
+ case AIO_GsaveIncludeDocument :
+ _handleGsaveIncludeDocument();
+ return true;
+ break;
+ case AIO_Grestore :
+ if (m_delegate->m_embeddedHandler) m_delegate->m_embeddedHandler->gotGrestore();
+ return true;
+ break;
+ case AIO_FontEncoding :
+ _handleFontEncoding();
+ return true;
+ break;
+ case AIO_SetCurrentText :
+ _handleSetCurrentText();
+ return true;
+ break;
+ case AIO_TextBlockFillStroke :
+ _handleTextBlock (TO_FillStroke);
+ return true;
+ break;
+ case AIO_TextBlockFill :
+ _handleTextBlock (TO_Fill);
+ return true;
+ break;
+ case AIO_TextBlockAppend :
+ _handleTextBlock (TO_Append);
+ return true;
+ break;
+ case AIO_TextBlockIgnore :
+ _handleTextBlock (TO_Ignore);
+ return true;
+ break;
+ case AIO_TextBlockStroke :
+ _handleTextBlock (TO_Stroke);
+ return true;
+ break;
+ case AIO_TextOutput :
+ _handleTextOutput ();
+ return true;
+ break;
+ case AIO_TextBlockEnd :
+ if (m_delegate->m_textHandler) m_delegate->m_textHandler->gotTextBlockEnd();
+ return true;
+ break;
+ default :
+ return false;
+ }
+ return false;
+}
+
+
+void AI88Handler::_handleSetFillColorCMYK()
+{
+ double k = m_delegate->getDoubleValue();
+ double y = m_delegate->getDoubleValue();
+ double m = m_delegate->getDoubleValue();
+ double c = m_delegate->getDoubleValue();
+
+ if (m_delegate->m_debug) qDebug ("values 1 are %f %f %f %f",c,m,y,k);
+ AIColor color (c,m,y,k);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotFillColor (color);
+}
+
+void AI88Handler::_handleSetFillPattern()
+{
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ka = m_delegate->getDoubleValue();
+ double k = m_delegate->getDoubleValue();
+ double r = m_delegate->getDoubleValue();
+ double rf = m_delegate->getDoubleValue();
+ double angle = m_delegate->getDoubleValue();
+ double sy = m_delegate->getDoubleValue();
+ double sx = m_delegate->getDoubleValue();
+ double py = m_delegate->getDoubleValue();
+ double px = m_delegate->getDoubleValue();
+
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &name = elem2.toString();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotFillPattern (name.latin1(), px, py, sx, sy, angle, rf, r, k, ka, aval);
+}
+
+void AI88Handler::_handleSetStrokePattern()
+{
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ka = m_delegate->getDoubleValue();
+ double k = m_delegate->getDoubleValue();
+ double r = m_delegate->getDoubleValue();
+ double rf = m_delegate->getDoubleValue();
+ double angle = m_delegate->getDoubleValue();
+ double sy = m_delegate->getDoubleValue();
+ double sx = m_delegate->getDoubleValue();
+ double py = m_delegate->getDoubleValue();
+ double px = m_delegate->getDoubleValue();
+
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &name = elem2.toString();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotStrokePattern (name.latin1(), px, py, sx, sy, angle, rf, r, k, ka, aval);
+}
+
+
+void AI88Handler::_handleSetStrokeColorCMYK()
+{
+ double k = m_delegate->getDoubleValue();
+ double y = m_delegate->getDoubleValue();
+ double m = m_delegate->getDoubleValue();
+ double c = m_delegate->getDoubleValue();
+ if (m_delegate->m_debug) qDebug ("values 2 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotStrokeColor (color);
+}
+
+void AI88Handler::_handleSetFillColorGray()
+{
+ double g = m_delegate->getDoubleValue();
+ if (m_delegate->m_debug) qDebug ("values 3 are %f",g);
+
+ AIColor color (g);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotFillColor (color);
+}
+
+void AI88Handler::_handleSetStrokeColorGray()
+{
+ double g = m_delegate->getDoubleValue();
+ if (m_delegate->m_debug) qDebug ("values 4 are %f",g);
+
+ AIColor color (g);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotStrokeColor (color);
+}
+
+void AI88Handler::_handleSetFillColorCustom()
+{
+ double g = m_delegate->getDoubleValue();
+ const QString name = m_delegate->getStringValue();
+ double k = m_delegate->getDoubleValue();
+ double y = m_delegate->getDoubleValue();
+ double m = m_delegate->getDoubleValue();
+ double c = m_delegate->getDoubleValue();
+ if (m_delegate->m_debug) qDebug ("values 5 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k,name.latin1(),g);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotFillColor (color);
+}
+
+void AI88Handler::_handleSetDash()
+{
+// qDebug ("found dash operation");
+ double fval = m_delegate->getDoubleValue();
+
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotDash (aval, fval);
+// qDebug ("dash operation finished");
+}
+
+void AI88Handler::_handlePatternDefinition()
+{
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ury = m_delegate->getDoubleValue();
+ double urx = m_delegate->getDoubleValue();
+ double lly = m_delegate->getDoubleValue();
+ double llx = m_delegate->getDoubleValue();
+
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &name = elem2.toString();
+
+ if (m_delegate->m_documentHandler) m_delegate->m_documentHandler->gotPatternDefinition (name.latin1(), aval, llx, lly, urx, ury);
+}
+
+void AI88Handler::_handleGsaveIncludeDocument() {
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &name = elem2.toString();
+
+ int ury = m_delegate->getIntValue();
+ int urx = m_delegate->getIntValue();
+ int lly = m_delegate->getIntValue();
+ int llx = m_delegate->getIntValue();
+
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ if (m_delegate->m_embeddedHandler) m_delegate->m_embeddedHandler->gotGsaveIncludeDocument (aval, llx,lly,urx,ury,name.latin1());
+}
+
+void AI88Handler::_handleSetCurrentText() {
+ int iAlign = m_delegate->getIntValue();
+ TextAlign ta = TA_HLeft;
+
+ switch (iAlign)
+ {
+ case 0 : ta = TA_HLeft; break;
+ case 1 : ta = TA_HCenter; break;
+ case 2 : ta = TA_HRight; break;
+ case 3: ta = TA_VTop; break;
+ case 4 : ta = TA_VCenter; break;
+ case 5 : ta = TA_VBottom; break;
+ }
+
+ double kerning = m_delegate->getDoubleValue();
+ double leading = m_delegate->getDoubleValue();
+ double size = m_delegate->getDoubleValue();
+
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &fontname = elem2.toReference();
+
+ if (m_delegate->m_textHandler) m_delegate->m_textHandler->gotFontDefinition (fontname.latin1(), size, leading, kerning, ta);
+
+}
+
+void AI88Handler::_handleTextBlock (TextOperation to) {
+ AIElement elem (m_delegate->m_stack.top());
+ qDebug ("to element is (%s)",elem.typeName());
+ m_delegate->m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ if (m_delegate->m_textHandler) m_delegate->m_textHandler->gotTextBlockBegin (aval, to);
+}
+
+void AI88Handler::_handleTextOutput () {
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+
+ const QString &text = elem.toString();
+
+ int length = -1;
+
+ if (m_delegate->m_stack.empty())
+ {
+ AIElement elem2 (m_delegate->m_stack.top());
+ if (elem2.type() == AIElement::Int)
+ {
+ length = elem2.asInt();
+ m_delegate->m_stack.pop();
+ }
+ }
+ if (m_delegate->m_textHandler) m_delegate->m_textHandler->gotTextOutput (text.latin1(), length);
+}
+
+void AI88Handler::_handleFontEncoding()
+{
+ while (m_delegate->m_stack.top().type() != AIElement::Reference) {
+ m_delegate->m_stack.pop();
+ }
+
+ AIElement elem (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+ const QString &oldFont = elem.toReference();
+
+ AIElement elem2 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+ const QString &newFont = elem2.toReference();
+
+ AIElement elem3 (m_delegate->m_stack.top());
+ m_delegate->m_stack.pop();
+ const QValueVector<AIElement> encodingData = elem3.toElementArray();
+
+ if (m_delegate->m_textHandler) m_delegate->m_textHandler->gotFontEncoding (encodingData, oldFont.latin1(), newFont.latin1());
+}
+
+void AI88Handler::_handleSetStrokeColorCustom()
+{
+ double g = m_delegate->getDoubleValue();
+ const QString name = m_delegate->getStringValue();
+ double k = m_delegate->getDoubleValue();
+ double y = m_delegate->getDoubleValue();
+ double m = m_delegate->getDoubleValue();
+ double c = m_delegate->getDoubleValue();
+ if (m_delegate->m_debug) qDebug ("values 6 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k,name.latin1(),g);
+
+ if (m_delegate->m_gstateHandler) m_delegate->m_gstateHandler->gotStrokeColor (color);
+}
diff --git a/filters/karbon/ai/ai88handler.h b/filters/karbon/ai/ai88handler.h
new file mode 100644
index 00000000..be031113
--- /dev/null
+++ b/filters/karbon/ai/ai88handler.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AI88HANDLER_H
+#define AI88HANDLER_H
+
+#include "aiparserbase.h"
+
+/**
+ *@author Dirk Schoenberger
+ */
+
+class AI88Handler {
+private:
+ AIParserBase *m_delegate;
+
+ void _handleSetDash();
+ void _handleSetStrokeColorCMYK();
+ void _handleSetFillColorCMYK();
+ void _handleSetStrokeColorGray();
+ void _handleSetFillColorGray();
+ void _handleSetStrokeColorCustom();
+ void _handleSetFillColorCustom();
+ void _handleSetFillPattern();
+ void _handleSetStrokePattern();
+ void _handlePatternDefinition();
+ void _handleGsaveIncludeDocument();
+ void _handleSetCurrentText();
+ void _handleTextBlock (TextOperation to);
+ void _handleTextOutput ();
+ void _handleFontEncoding();
+
+public:
+ AI88Handler(AIParserBase *delegate);
+ ~AI88Handler();
+
+ bool handleAIOperation (AIOperation op);
+};
+
+#endif
diff --git a/filters/karbon/ai/aicolor.cc b/filters/karbon/ai/aicolor.cc
new file mode 100644
index 00000000..67384167
--- /dev/null
+++ b/filters/karbon/ai/aicolor.cc
@@ -0,0 +1,100 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "aicolor.h"
+#include <stdlib.h>
+
+AIColor::AIColor(){
+ ctype = AIColor::CT_CMYK;
+ cdata.cmykdata.cvalue = 0;
+ cdata.cmykdata.mvalue = 0;
+ cdata.cmykdata.yvalue = 0;
+ cdata.cmykdata.kvalue = 0;
+}
+
+AIColor::AIColor( const AIColor& value ){
+ ctype = value.ctype;
+ memcpy (&cdata, &value.cdata, sizeof (cdata));
+}
+AIColor::AIColor( double c, double m, double y, double k ){
+ ctype = AIColor::CT_CMYK;
+ cdata.cmykdata.cvalue = c;
+ cdata.cmykdata.mvalue = m;
+ cdata.cmykdata.yvalue = y;
+ cdata.cmykdata.kvalue = k;
+}
+AIColor::AIColor( double c, double m, double y, double k, const char* colorname, double gray ){
+ ctype = AIColor::CT_CMYK_Key;
+ cdata.cmykdata.cvalue = c;
+ cdata.cmykdata.mvalue = m;
+ cdata.cmykdata.yvalue = y;
+ cdata.cmykdata.kvalue = k;
+ cdata.cmykdata.colorname = strdup (colorname);
+}
+AIColor::AIColor( double gray ){
+ ctype = AIColor::CT_Gray;
+ cdata.graydata = gray;
+}
+
+AIColor::~AIColor(){
+}
+
+void AIColor::toRGB (double &r, double &g, double &b)
+{
+ switch (ctype)
+ {
+ case CT_CMYK :
+ case CT_CMYK_Key :
+ r = 1 - cdata.cmykdata.cvalue - cdata.cmykdata.kvalue;
+ g = 1 - cdata.cmykdata.mvalue - cdata.cmykdata.kvalue;
+ b = 1 - cdata.cmykdata.yvalue - cdata.cmykdata.kvalue;
+ break;
+ case CT_Gray :
+ r = cdata.graydata;
+ g = cdata.graydata;
+ b = cdata.graydata;
+ break;
+ default :
+ qDebug ("unknown colortype %d", ctype);
+ }
+}
+
+void AIColor::toCMYK (double &c, double &m, double &y, double &k)
+{
+ switch (ctype)
+ {
+ case CT_CMYK :
+ case CT_CMYK_Key :
+ c = cdata.cmykdata.cvalue;
+ m = cdata.cmykdata.mvalue;
+ y = cdata.cmykdata.yvalue;
+ k = cdata.cmykdata.kvalue;
+ break;
+ case CT_Gray :
+ c = 0;
+ m = 0;
+ y = 0;
+ k = cdata.graydata;
+ break;
+ default :
+ qDebug ("unknown colortype %d", ctype);
+ }
+}
+
+
diff --git a/filters/karbon/ai/aicolor.h b/filters/karbon/ai/aicolor.h
new file mode 100644
index 00000000..b8cc1414
--- /dev/null
+++ b/filters/karbon/ai/aicolor.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AICOLOR_H
+#define AICOLOR_H
+
+#include <qstring.h>
+
+/**
+ *@author
+ */
+
+class AIColor {
+ public:
+ typedef enum { CT_CMYK, CT_CMYK_Key, CT_Gray } ColorType;
+
+ private:
+ ColorType ctype;
+
+ union {
+ struct {
+ double cvalue, mvalue, yvalue, kvalue;
+ char *colorname;
+ double graydata;
+ } cmykdata;
+ double graydata;
+ } cdata;
+public:
+ AIColor();
+ ~AIColor();
+ AIColor( const AIColor& );
+ AIColor( double c, double m, double y, double k );
+ AIColor( double c, double m, double y, double k, const char *colorname, double gray );
+ AIColor( double gray );
+
+ void toRGB (double &r, double &g, double &b);
+ void toCMYK (double &c, double &m, double &y, double &k);
+
+};
+
+#endif
diff --git a/filters/karbon/ai/aielement.cc b/filters/karbon/ai/aielement.cc
new file mode 100644
index 00000000..13887b50
--- /dev/null
+++ b/filters/karbon/ai/aielement.cc
@@ -0,0 +1,804 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "aielement.h"
+#include <qglobal.h>
+
+AIElement::Private::Private()
+{
+ typ = AIElement::Invalid;
+}
+
+AIElement::Private::Private( Private* d )
+{
+ switch( d->typ )
+ {
+ case AIElement::Invalid:
+ break;
+ case AIElement::String:
+ case AIElement::Reference:
+ case AIElement::Operator:
+ value.ptr = new QString( *((QString*)d->value.ptr) );
+ break;
+ case AIElement::CString:
+ // QCString is explicit shared
+ value.ptr = new QCString( *((QCString*)d->value.ptr) );
+ break;
+/* case AIElement::List:
+ value.ptr = new QValueList<AIElement>( *((QValueList<AIElement>*)d->value.ptr) );
+ break; */
+ case AIElement::ElementArray:
+ value.ptr = new QValueVector<AIElement>( *((QValueVector<AIElement>*)d->value.ptr) );
+ break;
+ case AIElement::Block:
+ value.ptr = new QValueVector<AIElement>( *((QValueVector<AIElement>*)d->value.ptr) );
+ break;
+ case AIElement::ByteArray:
+ value.ptr = new QByteArray( *((QByteArray*)d->value.ptr) );
+ break;
+ case AIElement::Int:
+ value.i = d->value.i;
+ break;
+ case AIElement::UInt:
+ value.u = d->value.u;
+ break;
+ case AIElement::Double:
+ value.d = d->value.d;
+ break;
+ case AIElement::Byte:
+ value.b = d->value.b;
+ break;
+ default:
+ Q_ASSERT( 0 );
+ }
+
+ typ = d->typ;
+}
+
+AIElement::Private::~Private()
+{
+ clear();
+}
+
+void AIElement::Private::clear()
+{
+ switch( typ )
+ {
+ case AIElement::String:
+ case AIElement::Operator:
+ case AIElement::Reference:
+ delete (QString*)value.ptr;
+ break;
+ case AIElement::CString:
+ delete (QCString*)value.ptr;
+ break;
+/* case AIElement::List:
+ delete (QValueList<AIElement>*)value.ptr;
+ break; */
+ case AIElement::ElementArray:
+ delete (QValueVector<AIElement>*)value.ptr;
+ break;
+ case AIElement::Block:
+ delete (QValueVector<AIElement>*)value.ptr;
+ break;
+ case AIElement::ByteArray:
+ delete (QByteArray*)value.ptr;
+ break;
+ case AIElement::Invalid:
+ case AIElement::Int:
+ case AIElement::UInt:
+ case AIElement::Double:
+ case AIElement::Byte:
+ break;
+ }
+
+ typ = AIElement::Invalid;
+}
+
+/*!
+ Constructs an invalid aielement.
+*/
+AIElement::AIElement()
+{
+ d = new Private;
+}
+
+/*!
+ Destroys the AIElement and the contained object.
+
+ Note that subclasses that reimplement clear() should reimplement
+ the destructor to call clear(). This destructor calls clear(), but
+ because it is the destructor, AIElement::clear() is called rather than
+ a subclass's clear().
+*/
+AIElement::~AIElement()
+{
+ if ( d->deref() )
+ delete d;
+}
+
+/*!
+ Constructs a copy of the aielement, \a p, passed as the argument to this
+ constructor. Usually this is a deep copy, but a shallow copy is made
+ if the stored data type is explicitly shared, as e.g. QImage is.
+*/
+AIElement::AIElement( const AIElement& p )
+{
+ d = new Private;
+ *this = p;
+}
+
+/*!
+ Constructs a new aielement with a string value, \a val.
+*/
+AIElement::AIElement( const QString& val, Type type )
+{
+ d = new Private;
+ d->typ = type;
+ d->value.ptr = new QString( val );
+}
+
+/*!
+ Constructs a new aielement with a C-string value, \a val.
+
+ If you want to modify the QCString after you've passed it to this
+ constructor, we recommend passing a deep copy (see
+ QCString::copy()).
+*/
+AIElement::AIElement( const QCString& val )
+{
+ d = new Private;
+ d->typ = CString;
+ d->value.ptr = new QCString( val );
+}
+
+/*!
+ Constructs a new aielement with a C-string value of \a val if \a val
+ is non-null. The aielement creates a deep copy of \a val.
+
+ If \a val is null, the resulting aielement has type Invalid.
+*/
+AIElement::AIElement( const char* val )
+{
+ d = new Private;
+ if ( val == 0 )
+ return;
+ d->typ = CString;
+ d->value.ptr = new QCString( val );
+}
+
+/*!
+ Constructs a new aielement with an integer value, \a val.
+*/
+AIElement::AIElement( int val )
+{
+ d = new Private;
+ d->typ = Int;
+ d->value.i = val;
+}
+
+/*!
+ Constructs a new aielement with an unsigned integer value, \a val.
+*/
+AIElement::AIElement( uint val )
+{
+ d = new Private;
+ d->typ = UInt;
+ d->value.u = val;
+}
+
+/*!
+ Constructs a new aielement with an byte value, \a val.
+*/
+AIElement::AIElement( uchar val )
+{
+ d = new Private;
+ d->typ = Byte;
+ d->value.b = val;
+}
+
+
+/*!
+ Constructs a new aielement with a floating point value, \a val.
+*/
+AIElement::AIElement( double val )
+{
+ d = new Private;
+ d->typ = Double;
+ d->value.d = val;
+}
+
+/*!
+ Constructs a new aielement with a list value, \a val.
+*/
+/* AIElement::AIElement( const QValueList<AIElement>& val )
+{
+ d = new Private;
+ d->typ = List;
+ d->value.ptr = new QValueList<AIElement>( val );
+} */
+
+AIElement::AIElement( const QValueVector<AIElement>& val, Type type )
+{
+ d = new Private;
+ d->typ = type;
+ d->value.ptr = new QValueVector<AIElement>( val );
+}
+
+AIElement::AIElement( const QByteArray& val )
+{
+ d = new Private;
+ d->typ = ByteArray;
+ d->value.ptr = new QByteArray( val );
+}
+
+/*!
+ Assigns the value of the aielement \a aielement to this aielement.
+
+ This is a deep copy of the aielement, but note that if the aielement
+ holds an explicitly shared type such as QImage, a shallow copy
+ is performed.
+*/
+AIElement& AIElement::operator= ( const AIElement& aielement )
+{
+ AIElement& other = (AIElement&)aielement;
+
+ other.d->ref();
+ if ( d->deref() )
+ delete d;
+
+ d = other.d;
+
+ return *this;
+}
+
+/*!
+ \internal
+*/
+void AIElement::detach()
+{
+ if ( d->count == 1 )
+ return;
+
+ d->deref();
+ d = new Private( d );
+}
+
+/*!
+ Returns the name of the type stored in the aielement.
+ The returned strings describe the C++ datatype used to store the
+ data: for example, "QFont", "QString", or "QValueList<AIElement>".
+ An Invalid aielement returns 0.
+*/
+const char* AIElement::typeName() const
+{
+ return typeToName( d->typ );
+}
+
+/*! Convert this aielement to type Invalid and free up any resources
+ used.
+*/
+void AIElement::clear()
+{
+ if ( d->count > 1 )
+ {
+ d->deref();
+ d = new Private;
+ return;
+ }
+
+ d->clear();
+}
+
+static const int ntypes = 11;
+static const char* const type_map[ntypes] =
+{
+ 0,
+// "QValueList<AIElement>",
+ "QString",
+ "int",
+ "uint",
+ "double",
+ "QCString",
+ "Operator",
+ "Reference",
+ "QValueVector<AIElement>",
+ "QByteArray",
+ "uchar",
+};
+
+/*!
+ Converts the enum representation of the storage type, \a typ, to its
+ string representation.
+*/
+const char* AIElement::typeToName( Type typ )
+{
+ if ( typ >= ntypes )
+ return 0;
+ return type_map[typ];
+}
+
+/*!
+ Converts the string representation of the storage type gven in \a
+ name, to its enum representation.
+
+ If the string representation cannot be converted to any enum
+ representation, the aielement is set to \c Invalid.
+*/
+AIElement::Type AIElement::nameToType( const char* name )
+{
+ for ( int i = 0; i < ntypes; i++ ) {
+ if ( !qstrcmp( type_map[i], name ) )
+ return (Type) i;
+ }
+ return Invalid;
+}
+
+/*!
+ Returns the aielement as a QString if the aielement has type()
+ String, CString, ByteArray, Int, Uint, Double,
+ or QString::null otherwise.
+
+ \sa asString()
+*/
+const QString AIElement::toString() const
+{
+ if ( d->typ == CString )
+ return QString::fromLatin1( toCString() );
+ if ( d->typ == Int )
+ return QString::number( toInt() );
+ if ( d->typ == UInt )
+ return QString::number( toUInt() );
+ if ( d->typ == Double )
+ return QString::number( toDouble() );
+ if ( d->typ == Byte )
+ return QString::number( toByte() );
+ if ( d->typ != String )
+ return QString::null;
+ return *((QString*)d->value.ptr);
+}
+
+const QString AIElement::toReference() const
+{
+ if ( d->typ != Reference )
+ return QString::null;
+ return *((QString*)d->value.ptr);
+}
+
+const QString AIElement::toOperator() const
+{
+ if ( d->typ != Operator )
+ return QString::null;
+ return *((QString*)d->value.ptr);
+}
+
+/*!
+ Returns the aielement as a QCString if the aielement has type()
+ CString or String, or a 0 otherwise.
+
+ \sa asCString()
+*/
+const QCString AIElement::toCString() const
+{
+ if ( d->typ == CString )
+ return *((QCString*)d->value.ptr);
+ if ( d->typ == String )
+ return ((QString*)d->value.ptr)->latin1();
+ if ( d->typ == Operator )
+ return ((QString*)d->value.ptr)->latin1();
+ if ( d->typ == Reference )
+ return ((QString*)d->value.ptr)->latin1();
+
+ return 0;
+}
+
+
+/*!
+ Returns the aielement as an int if the aielement has type()
+ String, CString, Int, UInt, Double, Byte, or 0 otherwise.
+
+ If \a ok is non-null, \a *ok is set to TRUE if the value could be
+ converted to an int and FALSE otherwise.
+
+ \sa asInt() canCast()
+*/
+int AIElement::toInt( bool * ok ) const
+{
+ if( d->typ == String )
+ return ((QString*)d->value.ptr)->toInt( ok );
+ if ( d->typ == CString )
+ return ((QCString*)d->value.ptr)->toInt( ok );
+ if ( ok )
+ *ok = canCast( UInt );
+ if( d->typ == Int )
+ return d->value.i;
+ if( d->typ == UInt )
+ return (int)d->value.u;
+ if( d->typ == Byte )
+ return (int)d->value.b;
+ if ( d->typ == Double )
+ return (int)d->value.d;
+ return 0;
+}
+
+uchar AIElement::toByte( bool * ok ) const
+{
+ if( d->typ == String )
+ return ((QString*)d->value.ptr)->toShort( ok );
+ if ( d->typ == CString )
+ return ((QCString*)d->value.ptr)->toShort( ok );
+ if ( ok )
+ *ok = canCast( UInt );
+ if( d->typ == Byte )
+ return d->value.b;
+ if( d->typ == Int )
+ return (uchar)d->value.i;
+ if( d->typ == UInt )
+ return (uchar)d->value.u;
+ if ( d->typ == Double )
+ return (uchar)d->value.d;
+ return 0;
+}
+
+
+/*!
+ Returns the aielement as an unsigned int if the aielement has type()
+ String, CString, UInt, Int, Double, Byte, or 0 otherwise.
+
+ If \a ok is non-null, \a *ok is set to TRUE if the value could be
+ converted to a uint and FALSE otherwise.
+
+ \sa asUInt()
+*/
+uint AIElement::toUInt( bool * ok ) const
+{
+ if( d->typ == String )
+ return ((QString*)d->value.ptr)->toUInt( ok );
+ if ( d->typ == CString )
+ return ((QCString*)d->value.ptr)->toUInt( ok );
+ if ( ok )
+ *ok = canCast( UInt );
+ if( d->typ == Int )
+ return d->value.i;
+ if( d->typ == UInt )
+ return (int)d->value.u;
+ if( d->typ == Byte )
+ return (int)d->value.b;
+ if ( d->typ == Double )
+ return (int)d->value.d;
+
+ return 0;
+}
+
+/*!
+ Returns the aielement as a double if the aielement has type()
+ String, CString, Double, Int, UInt, Byte, or 0.0 otherwise.
+
+ If \a ok is non-null, \a *ok is set to TRUE if the value could be
+ converted to a double and FALSE otherwise.
+
+ \sa asDouble()
+*/
+double AIElement::toDouble( bool * ok ) const
+{
+ if( d->typ == String )
+ return ((QString*)d->value.ptr)->toDouble( ok );
+ if ( d->typ == CString )
+ return ((QCString*)d->value.ptr)->toDouble( ok );
+ if ( ok )
+ *ok = canCast( Double );
+ if ( d->typ == Double )
+ return d->value.d;
+ if ( d->typ == Int )
+ return (double)d->value.i;
+ if ( d->typ == UInt )
+ return (double)d->value.u;
+ if ( d->typ == Byte )
+ return (double)d->value.b;
+ return 0.0;
+}
+
+/*!
+ Returns the aielement as a QValueList<AIElement> if the aielement has type()
+ List or StringList, or an empty list otherwise.
+
+ Note that if you want to iterate over the list, you should
+ iterate over a copy, e.g.
+ \code
+ QValueList<AIElement> list = myAIElement.toList();
+ QValueList<AIElement>::Iterator it = list.begin();
+ while( it != list.end() ) {
+ myProcessing( *it );
+ ++it;
+ }
+ \endcode
+
+ \sa asList()
+*/
+/* const QValueList<AIElement> AIElement::toList() const
+{
+ if ( d->typ == List )
+ return *((QValueList<AIElement>*)d->value.ptr);
+ return QValueList<AIElement>();
+} */
+
+const QValueVector<AIElement> AIElement::toElementArray() const
+{
+ if ( d->typ == ElementArray )
+ return *((QValueVector<AIElement>*)d->value.ptr);
+ return QValueVector<AIElement>();
+}
+
+const QValueVector<AIElement> AIElement::toBlock() const
+{
+ if ( d->typ == Block )
+ return *((QValueVector<AIElement>*)d->value.ptr);
+ return QValueVector<AIElement>();
+}
+
+
+const QByteArray AIElement::toByteArray() const
+{
+ if ( d->typ == ByteArray )
+ return *((QByteArray*)d->value.ptr);
+ return QByteArray();
+}
+
+#define Q_VARIANT_AS( f ) Q##f& AIElement::as##f() { \
+ if ( d->typ != f ) *this = AIElement( to##f() ); else detach(); return *((Q##f*)d->value.ptr);}
+
+Q_VARIANT_AS(String)
+Q_VARIANT_AS(CString)
+
+/*!
+ Returns the aielement's value as int reference.
+*/
+int& AIElement::asInt()
+{
+ detach();
+ if ( d->typ != Int ) {
+ int i = toInt();
+ d->clear();
+ d->value.i = i;
+ d->typ = Int;
+ }
+ return d->value.i;
+}
+
+/*!
+ Returns the aielement's value as unsigned int reference.
+*/
+uint& AIElement::asUInt()
+{
+ detach();
+ if ( d->typ != UInt ) {
+ uint u = toUInt();
+ d->clear();
+ d->value.u = u;
+ d->typ = UInt;
+ }
+ return d->value.u;
+}
+
+/*!
+ Returns the aielement's value as double reference.
+*/
+double& AIElement::asDouble()
+{
+ if ( d->typ != Double ) {
+ double dbl = toDouble();
+ d->clear();
+ d->value.d = dbl;
+ d->typ = Double;
+ }
+ return d->value.d;
+}
+
+/*!
+ Returns the aielement's value as byte reference.
+*/
+uchar& AIElement::asByte()
+{
+ detach();
+ if ( d->typ != Byte ) {
+ uchar b = toByte();
+ d->clear();
+ d->value.b = b;
+ d->typ = Byte;
+ }
+ return d->value.b;
+}
+
+
+/*!
+ Returns the aielement's value as aielement list reference.
+
+ Note that if you want to iterate over the list, you should
+ iterate over a copy, e.g.
+ \code
+ QValueList<AIElement> list = myAIElement.asList();
+ QValueList<AIElement>::Iterator it = list.begin();
+ while( it != list.end() ) {
+ myProcessing( *it );
+ ++it;
+ }
+ \endcode
+*/
+/* QValueList<AIElement>& AIElement::asList()
+{
+ if ( d->typ != List )
+ *this = AIElement( toList() );
+ return *((QValueList<AIElement>*)d->value.ptr);
+} */
+
+QValueVector<AIElement>& AIElement::asElementArray()
+{
+ if ( d->typ != ElementArray )
+ *this = AIElement( toElementArray() );
+ return *((QValueVector<AIElement>*)d->value.ptr);
+}
+
+QValueVector<AIElement>& AIElement::asBlock()
+{
+ if ( d->typ != Block )
+ *this = AIElement( toBlock() );
+ return *((QValueVector<AIElement>*)d->value.ptr);
+}
+
+
+QByteArray& AIElement::asByteArray()
+{
+ if ( d->typ != ByteArray )
+ *this = AIElement( toByteArray() );
+ return *((QByteArray*)d->value.ptr);
+}
+
+/*!
+ Returns TRUE if the aielement's type can be cast to the requested
+ type, \p t. Such casting is done automatically when calling the
+ toInt(), ... or asInt(), ... methods.
+
+ The following casts are done automatically:
+ <ul>
+ <li> CString => String
+ <li> Double => String, Int, UInt
+ <li> Int => String, Double, UInt
+ <li> String => CString, Int, Uint, Double
+ <li> UInt => String, Double, Int
+ </ul>
+*/
+bool AIElement::canCast( Type t ) const
+{
+ if ( d->typ == t )
+ return TRUE;
+ if ( t == Int && ( d->typ == String || d->typ == Double || d->typ == UInt || d->typ == Byte) )
+ return TRUE;
+ if ( t == UInt && ( d->typ == String || d->typ == Double || d->typ == Int || d->typ == Byte) )
+ return TRUE;
+ if ( t == Double && ( d->typ == String || d->typ == Int || d->typ == UInt || d->typ == Byte) )
+ return TRUE;
+ if ( t == CString && d->typ == String )
+ return TRUE;
+ if ( t == String && ( d->typ == CString || d->typ == Int || d->typ == UInt || d->typ == Double || d->typ == Byte) )
+ return TRUE;
+
+ return FALSE;
+}
+
+/*!
+ \brief Casts the aielement to the requested type.
+
+ If the cast cannot be
+ done, the aielement is set to the default value of the requested type
+ (e.g. an empty string if the requested type \p t is
+ AIElement::String, an empty point array if the requested type \p t is
+ AIElement::PointArray, etc).
+
+ \returns TRUE if the current type of the
+ aielement was successfully casted; otherwise returns FALSE.
+
+ \see canCast()
+*/
+
+bool AIElement::cast( Type t )
+{
+ switch ( t ) {
+/* case AIElement::List:
+ asList();
+ break; */
+ case AIElement::ElementArray:
+ asElementArray();
+ break;
+ case AIElement::Block:
+ asBlock();
+ break;
+ case AIElement::String:
+ asString();
+ break;
+ case AIElement::Int:
+ asInt();
+ break;
+ case AIElement::UInt:
+ asUInt();
+ break;
+ case AIElement::Double:
+ asDouble();
+ break;
+ case AIElement::CString:
+ asCString();
+ break;
+ case AIElement::Byte:
+ asByte();
+ break;
+ case AIElement::ByteArray:
+ asByteArray();
+ break;
+ default:
+ case AIElement::Invalid:
+ (*this) = AIElement();
+ }
+ return canCast( t );
+}
+
+/*! Compares this AIElement with \a v and returns TRUE if they are
+ equal; otherwise returns FALSE.
+*/
+
+bool AIElement::operator==( const AIElement &v ) const
+{
+ if ( !v.canCast( type() ) )
+ return FALSE;
+ switch( d->typ ) {
+/* case List:
+ return v.toList() == toList(); */
+ case ElementArray:
+ return v.toElementArray() == toElementArray();
+ case Block:
+ return v.toBlock() == toBlock();
+ case ByteArray:
+ return v.toByteArray() == toByteArray();
+
+ case String:
+ return v.toString() == toString();
+ case Operator:
+ return v.toOperator() == toOperator();
+ case Reference:
+ return v.toReference() == toReference();
+ case CString:
+ return v.toCString() == toCString();
+ case Int:
+ return v.toInt() == toInt();
+ case UInt:
+ return v.toUInt() == toUInt();
+ case Byte:
+ return v.toByte() == toByte();
+ case Invalid:
+ break;
+ }
+ return FALSE;
+}
+
+/*! Compares this AIElement with \a v and returns TRUE if they are
+ not equal; otherwise returns FALSE.
+*/
+
+bool AIElement::operator!=( const AIElement &v ) const
+{
+ return !( v == *this );
+}
diff --git a/filters/karbon/ai/aielement.h b/filters/karbon/ai/aielement.h
new file mode 100644
index 00000000..5c6ab045
--- /dev/null
+++ b/filters/karbon/ai/aielement.h
@@ -0,0 +1,151 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AIELEMENT_H
+#define AIELEMENT_H
+
+// #include <qvaluelist.h>
+#include <qvaluevector.h>
+
+class QString;
+class QCString;
+
+/**
+ *@author
+ */
+
+class AIElement {
+public:
+ enum Type {
+ Invalid,
+// List,
+ String,
+ Int,
+ UInt,
+ Double,
+ CString,
+ // Custom Types
+ Operator,
+ Reference,
+ ElementArray,
+ Block,
+ ByteArray,
+ Byte
+ };
+
+ AIElement();
+ ~AIElement();
+ AIElement( const AIElement& );
+ AIElement( const QString&, Type type = String );
+ AIElement( const QCString& );
+ AIElement( const char* );
+// AIElement( const QValueList<AIElement>& );
+ AIElement( const QValueVector<AIElement>&, Type type = ElementArray);
+ AIElement( int );
+ AIElement( uint );
+ AIElement( double );
+ AIElement( const QByteArray& );
+ AIElement( uchar );
+
+ AIElement& operator= ( const AIElement& );
+ bool operator==( const AIElement& ) const;
+ bool operator!=( const AIElement& ) const;
+
+ Type type() const;
+ const char* typeName() const;
+
+ bool canCast( Type ) const;
+ bool cast( Type );
+
+ bool isValid() const;
+
+ void clear();
+
+ const QString toString() const;
+ const QCString toCString() const;
+ int toInt( bool * ok=0 ) const;
+ uint toUInt( bool * ok=0 ) const;
+ double toDouble( bool * ok=0 ) const;
+// const QValueList<AIElement> toList() const;
+ const QValueVector<AIElement> toElementArray() const;
+ const QValueVector<AIElement> toBlock() const;
+
+ // Custom types
+ const QString toReference() const;
+ const QString toOperator() const;
+ const QByteArray toByteArray() const;
+ uchar toByte( bool * ok=0 ) const;
+
+// QValueListConstIterator<AIElement> listBegin() const;
+// QValueListConstIterator<AIElement> listEnd() const;
+ QString& asString();
+ QCString& asCString();
+ int& asInt();
+ uint& asUInt();
+ double& asDouble();
+// QValueList<AIElement>& asList();
+ QValueVector<AIElement>& asElementArray();
+ QValueVector<AIElement>& asBlock();
+
+ // Custom types
+ QString& asReference();
+ QString& asToken();
+ QByteArray& asByteArray();
+ uchar& asByte();
+
+ static const char* typeToName( Type typ );
+ static Type nameToType( const char* name );
+
+private:
+ void detach();
+
+ class Private : public QShared
+ {
+ public:
+ Private();
+ Private( Private* );
+ ~Private();
+
+ void clear();
+
+ Type typ;
+ union
+ {
+ uint u;
+ int i;
+ double d;
+ uchar b;
+ void *ptr;
+ } value;
+ };
+
+ Private* d;
+};
+
+inline AIElement::Type AIElement::type() const
+{
+ return d->typ;
+}
+
+inline bool AIElement::isValid() const
+{
+ return (d->typ != Invalid);
+}
+
+#endif
diff --git a/filters/karbon/ai/aiimport.cc b/filters/karbon/ai/aiimport.cc
new file mode 100644
index 00000000..a5e24f5b
--- /dev/null
+++ b/filters/karbon/ai/aiimport.cc
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qdom.h>
+#include <qcstring.h>
+#include <qfile.h>
+#include <qstring.h>
+
+#include <kgenericfactory.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include <kdebug.h>
+
+#include "aiimport.h"
+#include "karbonaiparserbase.h"
+
+class AiImportFactory : KGenericFactory<AiImport, KoFilter>
+{
+public:
+ AiImportFactory( void )
+ : KGenericFactory<AiImport, KoFilter>( "karbonaiimport" )
+ {}
+
+protected:
+ virtual void setupTranslations( void )
+ {
+ KGlobal::locale()->insertCatalogue( "kofficefilters" );
+ }
+};
+
+K_EXPORT_COMPONENT_FACTORY( libkarbonaiimport, AiImportFactory() )
+
+AiImport::AiImport( KoFilter*, const char*, const QStringList& )
+ : KoFilter()
+{
+}
+
+AiImport::~AiImport()
+{
+}
+
+KoFilter::ConversionStatus
+AiImport::convert( const QCString& from, const QCString& to )
+{
+ if ( from != "application/illustrator" || to != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+ QFile fileIn( m_chain->inputFile() );
+ if( !fileIn.open( IO_ReadOnly ) )
+ {
+ fileIn.close();
+ return KoFilter::FileNotFound;
+ }
+
+ QDomDocument doc ("DOC");
+ KarbonAIParserBase parser;
+
+ if (!parser.parse (fileIn, doc))
+ {
+ fileIn.close();
+ return KoFilter::CreationError;
+ }
+ QString result = doc.toString();
+
+ kdDebug() << result << endl;
+ KoStoreDevice* storeOut = m_chain->storageFile( "root", KoStore::Write );
+ if( !storeOut )
+ {
+ fileIn.close();
+ return KoFilter::StorageCreationError;
+ }
+
+ QCString cStr = result.latin1();
+ storeOut->writeBlock( cStr, cStr.size() - 1 );
+
+ return KoFilter::OK;
+}
+
+
+#include "aiimport.moc"
+
+
+
diff --git a/filters/karbon/ai/aiimport.h b/filters/karbon/ai/aiimport.h
new file mode 100644
index 00000000..2ec2d19b
--- /dev/null
+++ b/filters/karbon/ai/aiimport.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __AIIMPORT_H__
+#define __AIIMPORT_H__
+
+#include <KoFilter.h>
+
+#include "karbonaiparserbase.h"
+
+class QDomElement;
+class QTextStream;
+
+class AiImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ AiImport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~AiImport();
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+/* private:
+ QString m_result; */
+
+
+};
+
+#endif
+
+
diff --git a/filters/karbon/ai/ailexer.cc b/filters/karbon/ai/ailexer.cc
new file mode 100644
index 00000000..7b660f7f
--- /dev/null
+++ b/filters/karbon/ai/ailexer.cc
@@ -0,0 +1,514 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <qstringlist.h>
+#include "ailexer.h"
+
+#define CATEGORY_WHITESPACE -1
+#define CATEGORY_ALPHA -2
+#define CATEGORY_DIGIT -3
+#define CATEGORY_SPECIAL -4
+#define CATEGORY_LETTERHEX -5
+#define CATEGORY_INTTOOLONG -6
+
+#define CATEGORY_ANY -127
+
+#define MAX_INTLEN 9
+#define MIN_HEXCHARS 6
+
+#define STOP 0
+
+int iswhitespace(char c){
+ return (c==' ')||(c=='\n')||(c=='\t')||(c=='\r');
+}
+
+int isSpecial(char c){
+ return (c=='*')||(c=='_')||(c=='?')||(c=='~')||(c=='-')||(c=='^')||(c=='`')||(c=='!')||(c=='.')||(c=='@')||(c=='&')||(c=='$')||(c=='=');
+}
+
+int isletterhex(char c){
+ return (c=='A')||(c=='B')||(c=='C')||(c=='D')||(c=='E')||(c=='F');
+}
+
+const char*statetoa (State state){
+ switch (state)
+ {
+ case State_Comment : return "comment";
+ case State_Integer : return "integer";
+ case State_Float : return "float";
+ case State_String : return "string";
+ case State_Token : return "token";
+ case State_Reference : return "reference";
+ case State_Start : return "start";
+ case State_BlockStart : return "block start";
+ case State_BlockEnd : return "block end";
+ case State_ArrayStart : return "array start";
+ case State_ArrayEnd : return "array end";
+ case State_Byte : return "byte";
+ case State_ByteArray : return "byte array";
+ case State_StringEncodedChar : return "encoded char (string)";
+ case State_CommentEncodedChar : return "encoded char (comment)";
+ case State_ByteArray2 : return "byte array (mode 2)";
+ default : return "unknown";
+ }
+}
+
+typedef struct {
+ State oldState;
+ char c;
+ State newState;
+ Action action;
+} Transition;
+
+static Transition transitions[] = {
+ { State_Comment, '\n', State_Start, Action_Output},
+ { State_Comment, '\r', State_Start, Action_Output},
+ { State_Comment, '\\', State_CommentEncodedChar, Action_InitTemp},
+ { State_Comment, CATEGORY_ANY, State_Comment, Action_Copy},
+ { State_Integer, CATEGORY_DIGIT, State_Integer, Action_Copy},
+ { State_Integer, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_Integer, '.', State_Float, Action_Copy},
+ { State_Integer, ']', State_Start, Action_OutputUnget},
+ { State_Integer, '}', State_Start, Action_OutputUnget},
+ { State_Integer, '#', State_Byte, Action_Copy },
+ { State_Integer, '/', State_Start, Action_OutputUnget },
+ { State_Integer, '{', State_Start, Action_OutputUnget },
+ { State_Integer, '%', State_Start, Action_OutputUnget },
+ { State_Integer, CATEGORY_LETTERHEX, State_ByteArray2, Action_Copy },
+ { State_Integer, CATEGORY_INTTOOLONG, State_ByteArray2, Action_Copy },
+ { State_Integer, CATEGORY_ANY, State_Start, Action_Abort},
+ { State_Float, CATEGORY_DIGIT, State_Float, Action_Copy},
+ { State_Float, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_Float, ']', State_Start, Action_OutputUnget},
+ { State_Float, '}', State_Start, Action_OutputUnget},
+ { State_Float, CATEGORY_ANY, State_Start, Action_Abort},
+ { State_Token, CATEGORY_ALPHA, State_Token, Action_Copy},
+ { State_Token, CATEGORY_DIGIT, State_Token, Action_Copy},
+ { State_Token, CATEGORY_SPECIAL, State_Token, Action_Copy},
+ { State_Token, '}', State_Start, Action_OutputUnget},
+ { State_Token, ']', State_Start, Action_OutputUnget},
+ { State_Token, '{', State_BlockStart, Action_Output},
+ { State_Token, '}', State_BlockEnd, Action_Output},
+ { State_Token, '/', State_Start, Action_OutputUnget},
+ { State_Token, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_Token, CATEGORY_ANY, State_Start, Action_Abort},
+ { State_String, ')', State_Start, Action_Output},
+ { State_String, '\\', State_StringEncodedChar, Action_InitTemp},
+ { State_String, CATEGORY_ANY, State_String, Action_Copy},
+// { State_Array, CATEGORY_ALPHA, State_Array, Action_Copy},
+// { State_Array, CATEGORY_DIGIT, State_Array, Action_Copy},
+// { State_Array, ' ', State_Array, Action_Copy},
+ { State_BlockStart, CATEGORY_ANY, State_Start, Action_OutputUnget },
+ { State_BlockEnd, CATEGORY_ANY, State_Start, Action_OutputUnget },
+ { State_ArrayStart, CATEGORY_ANY, State_Start, Action_OutputUnget },
+ { State_ArrayEnd, CATEGORY_ANY, State_Start, Action_OutputUnget },
+ { State_Reference, '#', State_Reference, Action_Copy },
+ { State_Reference, CATEGORY_ALPHA, State_Reference, Action_Copy },
+ { State_Reference, CATEGORY_DIGIT, State_Reference, Action_Copy },
+ { State_Reference, CATEGORY_SPECIAL, State_Reference, Action_Copy },
+ { State_Reference, CATEGORY_ANY, State_Start, Action_OutputUnget },
+ { State_Byte, '/', State_Start, Action_OutputUnget },
+ { State_Byte, CATEGORY_DIGIT, State_Byte, Action_Copy},
+ { State_Byte, CATEGORY_ALPHA, State_Byte, Action_Copy},
+ { State_Byte, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_ByteArray, '>', State_Start, Action_Output },
+ { State_ByteArray, CATEGORY_ALPHA, State_ByteArray, Action_Copy },
+ { State_ByteArray, CATEGORY_DIGIT, State_ByteArray, Action_Copy },
+ { State_ByteArray, CATEGORY_WHITESPACE, State_ByteArray, Action_Ignore },
+ { State_ByteArray, CATEGORY_ANY, State_Start, Action_Abort },
+ { State_StringEncodedChar, '\\', State_String, Action_Copy},
+ { State_StringEncodedChar, CATEGORY_DIGIT, State_StringEncodedChar, Action_CopyTemp},
+ { State_StringEncodedChar, CATEGORY_ANY, State_String, Action_DecodeUnget},
+ { State_CommentEncodedChar, '\\', State_Comment, Action_Copy},
+ { State_CommentEncodedChar, CATEGORY_DIGIT, State_CommentEncodedChar, Action_CopyTemp},
+ { State_CommentEncodedChar, CATEGORY_ANY, State_Comment, Action_DecodeUnget},
+ { State_ByteArray2, '\n', State_Start, Action_Output},
+ { State_ByteArray2, '\r', State_Start, Action_Output},
+ { State_ByteArray2, '}', State_Start, Action_ByteArraySpecial},
+ { State_ByteArray2, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_ByteArray2, CATEGORY_DIGIT, State_ByteArray2, Action_Copy},
+ { State_ByteArray2, CATEGORY_LETTERHEX, State_ByteArray2, Action_Copy},
+ { State_ByteArray2, CATEGORY_ALPHA, State_Token, Action_Copy},
+ { State_ByteArray2, CATEGORY_ANY, State_Start, Action_Abort},
+ { State_Start, '%', State_Comment, Action_Ignore},
+ { State_Start, CATEGORY_DIGIT, State_Integer, Action_Copy},
+ { State_Start, '-', State_Integer, Action_Copy},
+ { State_Start, '+', State_Integer, Action_Copy},
+ { State_Start, '.', State_Float, Action_Copy},
+ { State_Start, '/', State_Reference, Action_Ignore },
+ { State_Start, '(', State_String, Action_Ignore},
+ { State_Start, '{', State_BlockStart, Action_Copy},
+ { State_Start, '}', State_BlockEnd, Action_Copy},
+ { State_Start, '[', State_ArrayStart, Action_Copy},
+ { State_Start, ']', State_ArrayEnd, Action_Copy},
+ { State_Start, '<', State_ByteArray, Action_Ignore},
+ { State_Start, CATEGORY_ALPHA, State_Token, Action_Copy},
+ { State_Start, CATEGORY_WHITESPACE, State_Start, Action_Output},
+ { State_Start, CATEGORY_SPECIAL, State_Token, Action_Copy},
+ { State_Start, CATEGORY_LETTERHEX, State_ByteArray2, Action_Copy},
+ { State_Start, CATEGORY_ANY, State_Start, Action_Abort},
+ { State_Start, STOP, State_Start, Action_Abort}
+};
+
+AILexer::AILexer(){
+}
+AILexer::~AILexer(){
+}
+
+bool AILexer::parse (QIODevice& fin){
+ char c;
+
+ m_buffer.clear();
+ m_curState = State_Start;
+
+ parsingStarted();
+
+ while (!fin.atEnd())
+ {
+ c = fin.getch ();
+
+// qDebug ("got %c", c);
+
+ State newState;
+ Action action;
+
+ nextStep (c, &newState, &action);
+
+ switch (action)
+ {
+ case Action_Copy :
+ m_buffer.append (c);
+ break;
+ case Action_CopyOutput :
+ m_buffer.append (c);
+ doOutput();
+ break;
+ case Action_Output :
+ doOutput();
+ break;
+ case Action_OutputUnget :
+ doOutput();
+ fin.ungetch(c);
+ break;
+ case Action_Ignore :
+ /* ignore */
+ break;
+ case Action_Abort :
+ qWarning ( "state %s / %s char %c (%d)" , statetoa(m_curState), statetoa(newState), c, c );
+ parsingAborted();
+ return false;
+ break;
+ case Action_InitTemp :
+ m_temp.clear();
+ break;
+ case Action_CopyTemp :
+ m_temp.append (c);
+ break;
+ case Action_DecodeUnget :
+ m_buffer.append (decode());
+ fin.ungetch(c);
+ break;
+ // in Postscript Quelltext: Kombination F}
+ case Action_ByteArraySpecial :
+ m_curState = State_Token;
+ doOutput();
+ fin.ungetch(c);
+ break;
+ default :
+ qWarning ( "unknown action: %d ", action);
+ }
+
+ m_curState = newState;
+ }
+
+ parsingFinished();
+ return true;
+}
+
+void AILexer::doOutput ()
+{
+ if (m_buffer.length() == 0) return;
+ switch (m_curState)
+ {
+ case State_Comment :
+ gotComment (m_buffer.latin1());
+ break;
+ case State_Integer :
+ gotIntValue (m_buffer.toInt());
+ break;
+ case State_Float :
+ gotDoubleValue (m_buffer.toFloat());
+ break;
+ case State_String :
+ gotStringValue (m_buffer.latin1());
+ break;
+ case State_Token :
+ gotToken (m_buffer.latin1());
+ break;
+ case State_Reference :
+ gotReference (m_buffer.latin1());
+ break;
+ case State_BlockStart :
+ gotBlockStart ();
+ break;
+ case State_BlockEnd :
+ gotBlockEnd ();
+ break;
+ case State_Start :
+ break;
+ case State_ArrayStart :
+ gotArrayStart ();
+ break;
+ case State_ArrayEnd :
+ gotArrayEnd ();
+ break;
+ case State_Byte :
+ gotByte (getByte());
+ break;
+ case State_ByteArray :
+ case State_ByteArray2 :
+ doHandleByteArray ();
+ break;
+ default:
+ qWarning ( "unknown state: %d", m_curState );
+ }
+
+ m_buffer.clear();
+}
+
+void AILexer::gotComment (const char *value) {
+ qDebug ( "gotComment: %s ", value );
+}
+
+void AILexer::gotIntValue (int value) {
+ qDebug ( "gotInt: %d ", value );
+}
+
+void AILexer::gotDoubleValue (double value) {
+ qDebug ( "gotDouble: %f ", value );
+}
+
+void AILexer::gotStringValue (const char *value) {
+ qDebug ( "gotString: %s ", value );
+}
+
+void AILexer::gotToken (const char *value) {
+ qDebug ( "gotToken: %s ", value );
+}
+
+void AILexer::gotReference (const char *value) {
+ qDebug ( "gotReference: %s ", value );
+}
+
+void AILexer::gotBlockStart (){
+ qDebug ( "gotBlockStart" );
+}
+
+void AILexer::gotBlockEnd (){
+ qDebug ( "gotBlockEnd" );
+}
+
+void AILexer::gotArrayStart (){
+ qDebug ( "gotArrayStart" );
+}
+
+void AILexer::gotArrayEnd (){
+ qDebug ( "gotArrayEnd" );
+}
+
+void AILexer::parsingStarted() {
+ qDebug ( "parsing started" );
+}
+
+void AILexer::parsingFinished() {
+ qDebug ( "parsing finished" );
+}
+
+void AILexer::parsingAborted() {
+ qDebug ( "parsing aborted" );
+}
+
+void AILexer::gotByte (uchar value) {
+ qDebug ( "got byte %d" , value );
+}
+
+void AILexer::gotByteArray (const QByteArray &data) {
+ qDebug ( "got byte array" );
+/* for ( uint i = 0; i < data.size(); i++ )
+ {
+ uchar value = data[i];
+ qDebug( "%d: %x", i, value );
+ }
+ qDebug ( "/byte array" ); */
+
+}
+
+
+void AILexer::nextStep (char c, State *newState, Action *newAction) {
+ int i=0;
+
+ while (true) {
+ Transition trans = transitions[i];
+
+ if (trans.c == STOP) {
+ *newState = trans.newState;
+ *newAction = trans.action;
+ return;
+ }
+
+ bool found = false;
+
+ if (trans.oldState == m_curState) {
+ switch (trans.c) {
+ case CATEGORY_WHITESPACE : found = isspace(c); break;
+ case CATEGORY_ALPHA : found = isalpha(c); break;
+ case CATEGORY_DIGIT : found = isdigit(c); break;
+ case CATEGORY_SPECIAL : found = isSpecial(c); break;
+ case CATEGORY_LETTERHEX : found = isletterhex(c); break;
+ case CATEGORY_INTTOOLONG : found = m_buffer.length() > MAX_INTLEN; break;
+ case CATEGORY_ANY : found = true; break;
+ default : found = (trans.c == c);
+ }
+
+ if (found) {
+ *newState = trans.newState;
+ *newAction = trans.action;
+
+ return;
+ }
+ }
+
+
+ i++;
+ }
+}
+
+void AILexer::doHandleByteArray ()
+{
+ // Special case - too short
+ if (m_buffer.length () < MIN_HEXCHARS)
+ {
+ gotToken (m_buffer.latin1());
+ return;
+ }
+
+ uint strIdx = 0;
+ uint arrayIdx = 0;
+
+ QByteArray data (m_buffer.length() >> 1);
+
+ while (strIdx < m_buffer.length())
+ {
+ const QString &item = m_buffer.mid (strIdx, 2);
+ uchar val = item.toShort(NULL, 16);
+ data[arrayIdx] = val;
+ strIdx += 2;
+ arrayIdx++;
+ }
+
+ gotByteArray (data);
+}
+
+uchar AILexer::getByte()
+{
+// qDebug ("convert string to byte (%s)", m_buffer.latin1());
+
+ QStringList list = QStringList::split ("#", m_buffer.toString());
+ int radix = list[0].toShort();
+ uchar value = list[1].toShort (NULL, radix);
+
+ return value;
+}
+
+uchar AILexer::decode()
+{
+ uchar value = m_temp.toString().toShort(NULL, 8);
+// qDebug ("got encoded char %c",value);
+ return value;
+}
+
+/* StringBuffer implementation */
+
+int initialSize = 20;
+int addSize = 10;
+
+StringBuffer::StringBuffer () {
+ m_buffer = (char*)calloc (initialSize, sizeof(char));
+ m_length = 0;
+ m_capacity = initialSize;
+}
+
+StringBuffer::~StringBuffer (){
+ free(m_buffer);
+}
+
+void StringBuffer::append (char c){
+ ensureCapacity(m_length + 1);
+ m_buffer[m_length] = c;
+ m_length++;
+}
+
+void StringBuffer::clear(){
+ for (uint i=0; i<m_length; i++) m_buffer[i] = '\0';
+ m_length = 0;
+}
+
+QString StringBuffer::toString() const {
+ QString ret(m_buffer);
+ return ret;
+}
+
+void StringBuffer::ensureCapacity (int p_capacity) {
+ if (m_capacity >= p_capacity) return;
+
+ int newSize = m_capacity + addSize;
+ if (p_capacity > newSize) newSize = p_capacity;
+
+ char* oldBuffer = m_buffer;
+ char *newBuffer = (char*)calloc (newSize, sizeof(char));
+ strcpy (newBuffer, m_buffer);
+ free(oldBuffer);
+ m_buffer = newBuffer;
+ m_capacity = newSize;
+}
+
+uint StringBuffer::length() {
+ return m_length;
+}
+
+double StringBuffer::toFloat() {
+ QString data = toString();
+ return data.toFloat();
+}
+
+int StringBuffer::toInt() {
+ QString data = toString();
+ return data.toInt();
+}
+
+const char *StringBuffer::latin1() {
+ return m_buffer;
+}
+
+QString StringBuffer::mid( uint index, uint len) const {
+ QString data = toString();
+ return data.mid(index,len);
+}
diff --git a/filters/karbon/ai/ailexer.h b/filters/karbon/ai/ailexer.h
new file mode 100644
index 00000000..c53aab66
--- /dev/null
+++ b/filters/karbon/ai/ailexer.h
@@ -0,0 +1,123 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AILEXER_H
+#define AILEXER_H
+
+#include <qiodevice.h>
+#include <qstring.h>
+
+/**
+ *@author Dirk Schnberger
+ */
+typedef enum {
+ State_Comment=0,
+ State_Integer,
+ State_Float,
+ State_String,
+ State_Token,
+ State_Reference,
+ State_Start,
+ State_BlockStart,
+ State_BlockEnd,
+ State_ArrayStart,
+ State_ArrayEnd,
+ State_Byte,
+ State_ByteArray,
+ State_StringEncodedChar,
+ State_CommentEncodedChar,
+ State_ByteArray2
+} State;
+
+typedef enum {
+ Action_Copy=1,
+ Action_CopyOutput,
+ Action_Output,
+ Action_Ignore,
+ Action_Abort,
+ Action_OutputUnget,
+ Action_InitTemp,
+ Action_CopyTemp,
+ Action_DecodeUnget,
+ Action_ByteArraySpecial
+} Action;
+
+class StringBuffer {
+public:
+ StringBuffer ();
+ virtual ~StringBuffer ();
+
+ void append (char c);
+ void clear();
+ QString toString() const;
+ uint length();
+ double toFloat();
+ int toInt();
+ const char *latin1();
+ QString mid( uint index, uint len=0xffffffff) const;
+private:
+ char *m_buffer;
+ uint m_length;
+ int m_capacity;
+
+ void ensureCapacity (int p_capacity);
+};
+
+class AILexer {
+public:
+ AILexer();
+ virtual ~AILexer();
+
+ virtual bool parse (QIODevice& fin);
+private:
+ State m_curState;
+ StringBuffer m_buffer;
+ StringBuffer m_temp;
+
+/* State nextState (char c);
+ Action nextAction (char c); */
+
+ void nextStep (char c, State* newState, Action* newAction);
+
+ void doOutput ();
+ void doHandleByteArray ();
+ uchar getByte();
+ uchar decode();
+
+protected:
+ virtual void parsingStarted();
+ virtual void parsingFinished();
+ virtual void parsingAborted();
+
+ virtual void gotComment (const char *value);
+ virtual void gotIntValue (int value);
+ virtual void gotDoubleValue (double value);
+ virtual void gotStringValue (const char *value);
+ virtual void gotToken (const char *value);
+ virtual void gotReference (const char *value);
+ virtual void gotBlockStart ();
+ virtual void gotBlockEnd ();
+ virtual void gotArrayStart ();
+ virtual void gotArrayEnd ();
+ virtual void gotByte (uchar value);
+ virtual void gotByteArray (const QByteArray &data);
+};
+
+#endif
+
diff --git a/filters/karbon/ai/aiparserbase.cc b/filters/karbon/ai/aiparserbase.cc
new file mode 100644
index 00000000..63ace734
--- /dev/null
+++ b/filters/karbon/ai/aiparserbase.cc
@@ -0,0 +1,1337 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schönberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "aiparserbase.h"
+#include "ai88handler.h"
+#include "ai3handler.h"
+#include <qregexp.h>
+#include <qstringlist.h>
+
+typedef struct {
+ char* op;
+ AIOperation action;
+} AIOperationMapping;
+
+typedef struct {
+ char* op;
+ PSOperation action;
+} PSOperationMapping;
+
+typedef struct {
+ char* op;
+ CommentOperation action;
+} CommentOperationMapping;
+
+static AIOperationMapping aiMappings[] = {
+ { "k", AIO_SetFillColorCMYK },
+ { "K", AIO_SetStrokeColorCMYK },
+ { "g", AIO_SetFillColorGray },
+ { "G", AIO_SetStrokeColorGray },
+ { "x", AIO_SetFillColorCustom },
+ { "X", AIO_SetStrokeColorCustom },
+ { "p", AIO_SetFillPattern },
+ { "P", AIO_SetStrokePattern },
+ { "O", AIO_SetFillOverprinting },
+ { "R", AIO_SetStrokeOverprinting },
+ { "i", AIO_SetFlatness },
+ { "J", AIO_SetLineCap },
+ { "j", AIO_SetLineJoin },
+ { "M", AIO_SetMiterLimit },
+ { "w", AIO_SetLineWidth },
+ { "d", AIO_SetDash },
+ { "q", AIO_BeginGroupClip },
+ { "Q", AIO_EndGroupClip },
+ { "m", AIO_MoveTo },
+ { "l", AIO_LineToSmooth },
+ { "L", AIO_LineToCorner },
+ { "c", AIO_CurveToSmooth },
+ { "C", AIO_CurveToCorner },
+
+ { "v", AIO_CurveToOmitC1Smooth },
+ { "V", AIO_CurveToOmitC1Corner },
+ { "y", AIO_CurveToOmitC2Smooth },
+ { "Y", AIO_CurveToOmitC2Corner },
+
+ { "H", AIO_PathIgnoreNoReset },
+ { "h", AIO_PathIgnoreNoResetClose },
+ { "W", AIO_PathClipPath },
+ { "N", AIO_PathIgnoreReset },
+ { "n", AIO_PathIgnoreResetClose },
+ { "F", AIO_PathFillNonZero },
+ { "f", AIO_PathFillNonZeroClose },
+ { "B", AIO_PathFillNoReset },
+ { "b", AIO_PathFillNoResetClose },
+ { "S", AIO_PathStroke },
+ { "s", AIO_PathStrokeClose },
+ { "D", AIO_SetWindingOrder },
+ { "Z", AIO_FontEncoding },
+ { "E", AIO_PatternDefinition },
+ { "A", AIO_LockElement },
+
+ { "z", AIO_SetCurrentText },
+ { "a", AIO_TextBlockFillStroke },
+ { "e", AIO_TextBlockFill },
+ { "I", AIO_TextBlockAppend },
+ { "o", AIO_TextBlockIgnore },
+ { "r", AIO_TextBlockStroke },
+ { "t", AIO_TextOutput },
+ { "T", AIO_TextBlockEnd },
+ { "`", AIO_GsaveIncludeDocument },
+ { "~", AIO_Grestore },
+
+ { "u", AIO_BeginGroupNoClip },
+ { "U", AIO_EndGroupNoClip },
+ { "*u", AIO_BeginCombination },
+ { "*U", AIO_EndCombination },
+
+ { "XR", AIO_SetFillMode },
+
+ { NULL, AIO_Other }
+};
+
+static PSOperationMapping psMappings[] = {
+ { "get", PSO_Get },
+ { "exec", PSO_Exec },
+ { "string", PSO_String },
+ { "bind", PSO_Bind },
+ { "def", PSO_Def },
+ { "userdict", PSO_Userdict },
+ { "dict", PSO_Dict },
+ { "dup", PSO_Dup },
+ { "begin", PSO_Begin },
+ { "put", PSO_Put },
+ { NULL, PSO_Other },
+};
+
+static CommentOperationMapping commentMappings[] = {
+ { "BeginProlog", CO_BeginProlog },
+ { "BeginSetup", CO_BeginSetup },
+ { "BeginProcSet", CO_BeginProcSet },
+ { "BeginResource", CO_BeginResource },
+ { "BeginEncoding", CO_BeginEncoding },
+ { "BeginPattern", CO_BeginPattern },
+ { "BeginDocument", CO_BeginPattern },
+ { "Trailer", CO_Trailer },
+ { "EndProlog", CO_EndProlog },
+ { "EndSetup", CO_EndSetup },
+ { "EndProcSet", CO_EndProcSet },
+ { "EndResource", CO_EndResource },
+ { "EndEncoding", CO_EndEncoding },
+ { "EndPattern", CO_EndPattern },
+ { "EndDocument", CO_EndDocument },
+
+ { "Title", CO_Title },
+ { "Creator", CO_Creator },
+
+ { "EOF", CO_Ignore },
+ { "Note", CO_Ignore },
+ { "EndComments", CO_Ignore },
+ { "PS-Adobe", CO_Ignore },
+
+ { "BoundingBox", CO_BoundingBox },
+ { "TemplateBox", CO_TemplateBox },
+ { "AI3_Margin", CO_Margin },
+
+ { "For", CO_For },
+ { "CreationDate", CO_CreationDate },
+ { "DocumentFonts", CO_DocumentFonts },
+ { "DocumentFiles", CO_DocumentFiles },
+ { "ColorUsage", CO_ColorUsage },
+ { "DocumentProcSets", CO_DocumentProcSets },
+ { "DocumentSuppliedProcSets", CO_DocumentSuppliedProcSets },
+
+ { "DocumentProcessColors", CO_DocumentProcessColors },
+ { "DocumentCustomColors", CO_DocumentCustomColors },
+ { "CMYKCustomColor", CO_CMYKCustomColor },
+ { "TileBox", CO_TileBox },
+ { "%+", CO_Continuation },
+
+ { "Template", CO_Template },
+ { "PageOrigin", CO_PageOrigin },
+ { "PrinterName", CO_PrinterName },
+ { "PrinterRect", CO_PrinterRect },
+ { "Note", CO_Note },
+
+ { "DocumentNeededResources", CO_DocumentNeededResources },
+
+
+ { "IncludeFont", CO_IncludeFont },
+ { "BeginBrushPattern", CO_BeginBrushPattern },
+ { "EndBrushPattern", CO_EndBrushPattern },
+ { "BeginGradient", CO_BeginGradient },
+ { "EndGradient", CO_EndGradient },
+ { "BeginPalette", CO_BeginPalette },
+ { "EndPalette", CO_EndPalette },
+
+ { "IncludeFile", CO_IncludeFile },
+ { "IncludeResource", CO_IncludeResource },
+
+ { NULL, CO_Other }
+};
+
+AIParserBase::AIParserBase() : m_debug(false), m_ignoring(false), m_sink (DS_Other), m_continuationMode(CM_None)
+ {
+ m_gstateHandler = NULL;
+ m_structureHandler = NULL;
+ m_pathHandler = NULL;
+ m_miscGStateHandler = NULL;
+ m_documentHandler = NULL;
+ m_moduleHandler = NULL;
+ m_embeddedHandler = NULL;
+ m_ai88Handler = new AI88Handler(this);
+ m_ai3Handler = new AI3Handler(this);
+}
+
+AIParserBase::~AIParserBase(){
+ delete m_ai88Handler;
+ delete m_ai3Handler;
+
+}
+
+bool AIParserBase::parse (QIODevice& fin){
+ return AILexer::parse (fin);
+}
+
+void AIParserBase::gotComment (const char *value) {
+ int llx, lly, urx, ury;
+
+ CommentOperation cop = getCommentOperation (value);
+ switch (cop) {
+ case CO_BeginDocument :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Document, value);
+ break;
+ case CO_EndDocument :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Document, value);
+ break;
+ case CO_BeginPattern :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Pattern, value);
+ break;
+ case CO_EndPattern :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Pattern, value);
+ break;
+ case CO_BeginProlog :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Prolog, value);
+ break;
+ case CO_BeginProcSet :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_ProcSet, value);
+ if (m_debug) qDebug ("start ignoring");
+ m_ignoring = true;
+ break;
+ case CO_BeginResource :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Resource, value);
+ if (m_debug) qDebug ("start ignoring");
+ m_ignoring = true;
+ break;
+ case CO_BeginEncoding :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Encoding, value);
+ m_ignoring = false;
+ break;
+ case CO_IncludeFont :
+ if (m_debug) qDebug ("start ignoring");
+ m_ignoring = true;
+ break;
+ case CO_BeginBrushPattern :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_BrushPattern, value);
+ break;
+ case CO_BeginGradient :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Gradient, value);
+ break;
+ case CO_Trailer :
+ if (m_debug) qDebug ("start ignoring");
+ m_ignoring = true;
+ break;
+ case CO_BeginPalette :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Palette, value);
+ break;
+ case CO_BeginSetup :
+ if (m_moduleHandler) m_moduleHandler->gotBeginSection (ST_Setup, value);
+ break;
+ case CO_EndSetup :
+ cleanupArrays();
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Setup, value);
+ break;
+ case CO_EndProlog :
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Prolog, value);
+ break;
+ case CO_EndProcSet :
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_ProcSet, value);
+ if (m_debug) qDebug ("stop ignoring");
+ m_ignoring = false;
+ break;
+ case CO_EndResource :
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Resource, value);
+ if (m_debug) qDebug ("stop ignoring");
+ m_ignoring = false;
+ break;
+ case CO_EndEncoding :
+ cleanupArrays();
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Encoding, value);
+ break;
+ case CO_EndBrushPattern :
+ cleanupArrays();
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_BrushPattern, value);
+ break;
+ case CO_EndGradient :
+ cleanupArrays();
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Gradient, value);
+ break;
+ case CO_EndPalette :
+ cleanupArrays();
+ if (m_moduleHandler) m_moduleHandler->gotEndSection (ST_Palette, value);
+ break;
+ case CO_Ignore :
+ break;
+ case CO_BoundingBox :
+ if (getRectangle (value, llx, lly, urx, ury))
+ {
+ if (m_documentHandler) m_documentHandler->gotBoundingBox (llx, lly, urx, ury);
+ }
+ break;
+ case CO_TemplateBox :
+ if (getRectangle (value, llx, lly, urx, ury))
+ {
+ if (m_documentHandler) m_documentHandler->gotTemplateBox (llx, lly, urx, ury);
+ }
+ break;
+ case CO_Margin :
+ if (getRectangle (value, llx, lly, urx, ury))
+ {
+ if (m_documentHandler) m_documentHandler->gotMargin (llx, lly, urx, ury);
+ }
+ break;
+ case CO_Title :
+ if (m_documentHandler) m_documentHandler->gotTitle (getValue (value));
+ break;
+ case CO_Creator :
+ if (m_documentHandler) m_documentHandler->gotCreator (getValue (value));
+ break;
+ case CO_DocumentFonts :
+ _handleDocumentFonts (value);
+ m_continuationMode = CM_DocumentFonts;
+ break;
+ case CO_DocumentFiles :
+ _handleDocumentFiles (value);
+ m_continuationMode = CM_DocumentFiles;
+ break;
+ case CO_DocumentCustomColors :
+ _handleDocumentCustomColors (value);
+ m_continuationMode = CM_DocumentFiles;
+ break;
+ case CO_CMYKCustomColor :
+ _handleCMYKCustomColor (value);
+ m_continuationMode = CM_CMYKCustomColor;
+ break;
+ case CO_DocumentNeededResources :
+ _handleDocumentNeededResources (value);
+ m_continuationMode = CM_DocumentNeededResources;
+ break;
+ case CO_DocumentProcessColors :
+ _handleDocumentProcessColors (value);
+ break;
+ case CO_CreationDate :
+ _handleCreationDate (value);
+ break;
+ case CO_IncludeFile :
+ break;
+ case CO_IncludeResource :
+ _handleIncludeResource (value);
+ break;
+ case CO_Continuation :
+ switch (m_continuationMode) {
+ case CM_DocumentFonts : _handleDocumentFonts (value); break;
+ case CM_DocumentFiles : _handleDocumentFiles (value); break;
+ case CM_DocumentCustomColors : _handleDocumentCustomColors (value); break;
+ case CM_CMYKCustomColor : _handleCMYKCustomColor (value); break;
+ case CM_DocumentNeededResources : _handleDocumentNeededResources (value); break;
+
+ default : qWarning ("unknown continuation mode %d",m_continuationMode);
+ }
+ break;
+
+ default :
+ qWarning( "unhandled comment: %s", value );
+ }
+}
+
+void AIParserBase::handleElement (AIElement &element)
+{
+ if (m_ignoring) return;
+
+ if (m_sink == DS_Array)
+ {
+ if (m_debug) qDebug ("in mode array");
+ QValueVector<AIElement> &elementArray = m_arrayStack.top();
+ elementArray.push_back(element);
+ }
+ if (m_sink == DS_Block)
+ {
+ if (m_debug) qDebug ("in mode block");
+ QValueVector<AIElement> &elementArray = m_blockStack.top();
+ elementArray.push_back(element);
+ }
+ else
+ {
+ if (m_debug) qDebug ("in mode stack");
+ m_stack.push (element);
+ }
+}
+
+void AIParserBase::gotIntValue (int value) {
+ if (m_debug) qDebug ("got int value");
+ if (m_ignoring) return;
+ AIElement element (value);
+ handleElement (element);
+ if (m_debug) qDebug ("/got int value");
+}
+
+void AIParserBase::gotDoubleValue (double value) {
+ if (m_debug) qDebug ("got double value");
+ if (m_ignoring) return;
+ AIElement element (value);
+ handleElement (element);
+ if (m_debug) qDebug ("/got double value");
+}
+
+void AIParserBase::gotStringValue (const char *value) {
+ if (m_debug) qDebug ("got string value");
+ if (m_ignoring) return;
+ if (value == NULL) value = "";
+ if (m_debug) qDebug ("string: %s", value);
+ AIElement element (value);
+ handleElement (element);
+ if (m_debug) qDebug ("/got string value");
+
+}
+
+void AIParserBase::gotReference (const char *value) {
+ if (m_debug) qDebug ("got reference value");
+
+ if (m_ignoring) return;
+ if (value == NULL) value = "";
+ if (m_debug) qDebug ("reference: %s", value);
+ QString string(value);
+ AIElement element (string, AIElement::Reference);
+ handleElement (element);
+ if (m_debug) qDebug ("/got reference value");
+
+}
+
+void AIParserBase::gotByte (uchar value) {
+ if (m_debug) qDebug ("got byte value");
+
+ if (m_ignoring) return;
+ AIElement element (value);
+ handleElement (element);
+ if (m_debug) qDebug ("/got byte value");
+}
+
+void AIParserBase::gotByteArray (const QByteArray &data) {
+ if (m_ignoring) return;
+ AIElement element (data);
+ handleElement (element);
+}
+
+
+void AIParserBase::gotArrayStart () {
+ if (m_ignoring) return;
+ if (m_debug) qDebug ("got array start");
+
+ QValueVector<AIElement> array;
+ m_arrayStack.push (array);
+
+ m_sink = DS_Array;
+}
+
+void AIParserBase::gotBlockStart () {
+ if (m_ignoring) return;
+ if (m_debug) qDebug ("got block start");
+
+ QValueVector<AIElement> array;
+ m_blockStack.push (array);
+
+ m_sink = DS_Block;
+}
+
+void AIParserBase::gotArrayEnd () {
+ if (m_ignoring) return;
+ if (m_debug) qDebug ("got array end");
+
+ QValueVector<AIElement> stackArray = m_arrayStack.pop();
+
+ if (m_arrayStack.empty())
+ {
+ if (m_debug) qDebug ("put elements to stack");
+ AIElement realElement (stackArray);
+
+ if (m_debug) {
+ qDebug ("going to stack");
+ elementtoa (realElement);
+ qDebug ("done");
+ }
+ m_stack.push (realElement);
+
+ m_sink = DS_Other;
+ }
+ else
+ {
+ if (m_debug) qDebug ("put elements to nest stack level");
+ QValueVector<AIElement> currentTOS = m_arrayStack.top();
+ currentTOS.push_back (stackArray);
+ }
+}
+
+void AIParserBase::gotBlockEnd () {
+ if (m_ignoring) return;
+ if (m_debug) qDebug ("got block end");
+
+ QValueVector<AIElement> stackArray = m_blockStack.pop();
+
+ if (m_blockStack.empty())
+ {
+ if (m_debug) qDebug ("put elements to stack");
+ AIElement realElement (stackArray, AIElement::Block);
+
+ if (m_debug) {
+ qDebug ("going to stack");
+ elementtoa (realElement);
+ qDebug ("done");
+ }
+ m_stack.push (realElement);
+
+ m_sink = DS_Other;
+ }
+ else
+ {
+ if (m_debug) qDebug ("put elements to nest stack level");
+ QValueVector<AIElement> currentTOS = m_blockStack.top();
+ currentTOS.push_back (stackArray);
+ }
+}
+
+/*Ai88*/ /* void AIParserBase::_handleSetDash()
+{
+ double fval = getDoubleValue();
+
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+ if (m_gstateHandler) m_gstateHandler->gotDash (aval, fval);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetFillColorCMYK()
+{
+ double k = getDoubleValue();
+ double y = getDoubleValue();
+ double m = getDoubleValue();
+ double c = getDoubleValue();
+
+ if (m_debug) qDebug ("values 1 are %f %f %f %f",c,m,y,k);
+ AIColor color (c,m,y,k);
+
+ if (m_gstateHandler) m_gstateHandler->gotFillColor (color);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetFillPattern()
+{
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ka = getDoubleValue();
+ double k = getDoubleValue();
+ double r = getDoubleValue();
+ double rf = getDoubleValue();
+ double angle = getDoubleValue();
+ double sy = getDoubleValue();
+ double sx = getDoubleValue();
+ double py = getDoubleValue();
+ double px = getDoubleValue();
+
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+
+ const QString &name = elem2.toString();
+ if (m_gstateHandler) m_gstateHandler->gotFillPattern (name.latin1(), px, py, sx, sy, angle, rf, r, k, ka, aval);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetStrokePattern()
+{
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ka = getDoubleValue();
+ double k = getDoubleValue();
+ double r = getDoubleValue();
+ double rf = getDoubleValue();
+ double angle = getDoubleValue();
+ double sy = getDoubleValue();
+ double sx = getDoubleValue();
+ double py = getDoubleValue();
+ double px = getDoubleValue();
+
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+
+ const QString &name = elem2.toString();
+ if (m_gstateHandler) m_gstateHandler->gotStrokePattern (name.latin1(), px, py, sx, sy, angle, rf, r, k, ka, aval);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetStrokeColorCMYK()
+{
+ double k = getDoubleValue();
+ double y = getDoubleValue();
+ double m = getDoubleValue();
+ double c = getDoubleValue();
+ if (m_debug) qDebug ("values 2 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k);
+
+ if (m_gstateHandler) m_gstateHandler->gotStrokeColor (color);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetFillColorGray()
+{
+ double g = getDoubleValue();
+ if (m_debug) qDebug ("values 3 are %f",g);
+
+ AIColor color (g);
+
+ if (m_gstateHandler) m_gstateHandler->gotFillColor (color);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetStrokeColorGray()
+{
+ double g = getDoubleValue();
+ if (m_debug) qDebug ("values 4 are %f",g);
+
+ AIColor color (g);
+
+ if (m_gstateHandler) m_gstateHandler->gotStrokeColor (color);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetFillColorCustom()
+{
+ double g = getDoubleValue();
+ const QString &name = getStringValue();
+ double k = getDoubleValue();
+ double y = getDoubleValue();
+ double m = getDoubleValue();
+ double c = getDoubleValue();
+ if (m_debug) qDebug ("values 5 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k,name.latin1(),g);
+
+ if (m_gstateHandler) m_gstateHandler->gotFillColor (color);
+} */
+
+void AIParserBase::_handlePSGet() {
+ m_stack.pop();
+ m_stack.pop();
+
+ QString name ("xxx");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSExec() {
+ m_stack.pop();
+}
+
+void AIParserBase::_handlePSString() {
+ m_stack.pop();
+
+ QString name ("stringval");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSBind() {
+ m_stack.pop();
+
+ QString name ("bindentry");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSUserdict() {
+ QString name ("userdict");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSDict() {
+ m_stack.pop();
+ m_stack.pop();
+ m_stack.pop();
+
+ QString name ("dict");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSDup() {
+ AIElement &tos = m_stack.top();
+
+ AIElement copy (tos);
+ m_stack.push (copy);
+}
+
+void AIParserBase::_handlePSBegin() {
+ m_stack.pop();
+
+ QString name ("dictionary begin");
+ AIElement ref (name,AIElement::Reference);
+ m_stack.push (ref);
+}
+
+void AIParserBase::_handlePSPut() {
+ m_stack.pop();
+ m_stack.pop();
+}
+
+/*Ai88*/ /* void AIParserBase::_handlePatternDefinition()
+{
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ double ury = getDoubleValue();
+ double urx = getDoubleValue();
+ double lly = getDoubleValue();
+ double llx = getDoubleValue();
+
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+
+ const QString &name = elem2.toString();
+
+ if (m_documentHandler) m_documentHandler->gotPatternDefinition (name.latin1(), aval, llx, lly, urx, ury);
+} */
+
+void AIParserBase::_handlePSDef() {
+ // name ref
+ m_stack.pop();
+
+ // impl
+ m_stack.pop();
+}
+
+/*Ai88*/ /* void AIParserBase::_handleSetStrokeColorCustom()
+{
+ double g = getDoubleValue();
+ const QString &name = getStringValue();
+ double k = getDoubleValue();
+ double y = getDoubleValue();
+ double m = getDoubleValue();
+ double c = getDoubleValue();
+ if (m_debug) qDebug ("values 6 are %f %f %f %f",c,m,y,k);
+
+ AIColor color (c,m,y,k,name.latin1(),g);
+
+ if (m_gstateHandler) m_gstateHandler->gotStrokeColor (color);
+} */
+
+void AIParserBase::_handleDocumentFonts(const char *) {
+}
+
+void AIParserBase::_handleDocumentFiles(const char *) {
+}
+
+void AIParserBase::_handleDocumentCustomColors(const char *) {
+}
+
+void AIParserBase::_handleDocumentNeededResources(const char *data) {
+ if (!data) return;
+ QStringList items = QStringList::split (' ', data);
+
+ QString itemType = items[1];
+ QString name = items[2];
+ QString version = items[3];
+ QString release = items[4];
+}
+
+void AIParserBase::_handleIncludeResource(const char *data) {
+ if (!data) return;
+ QStringList items = QStringList::split (' ', data);
+
+ QString itemType = items[1];
+ QString name = items[2];
+ QString version = items[3];
+ QString release = items[4];
+
+ m_modules.push_back (name);
+}
+
+void AIParserBase::_handleDocumentProcessColors(const char *data) {
+ if (!data) return;
+
+ int colorSet = 0;
+ QString tmp (data);
+
+ signed int index;
+
+ index = tmp.find ("Cyan");
+ if (index > 0) colorSet |= PC_Cyan;
+
+ index = tmp.find ("Magenta");
+ if (index > 0) colorSet |= PC_Magenta;
+
+ index = tmp.find ("Yellow");
+ if (index > 0) colorSet |= PC_Yellow;
+
+ index = tmp.find ("Black");
+ if (index > 0) colorSet |= PC_Black;
+
+ if (m_documentHandler) m_documentHandler->gotProcessColors (colorSet);
+}
+
+void AIParserBase::_handleCMYKCustomColor(const char *) {
+}
+
+/*Ai88*/ /* void AIParserBase::_handleGsaveIncludeDocument() {
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+
+ const QString &name = elem2.toString();
+
+ int ury = getIntValue();
+ int urx = getIntValue();
+ int lly = getIntValue();
+ int llx = getIntValue();
+
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ if (m_embeddedHandler) m_embeddedHandler->gotGsaveIncludeDocument (aval, llx,lly,urx,ury,name.latin1());
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleSetCurrentText() {
+ int iAlign = getIntValue();
+ TextAlign ta = TA_HLeft;
+
+ switch (iAlign)
+ {
+ case 0 : ta = TA_HLeft; break;
+ case 1 : ta = TA_HCenter; break;
+ case 2 : ta = TA_HRight; break;
+ case 3: ta = TA_VTop; break;
+ case 4 : ta = TA_VCenter; break;
+ case 5 : ta = TA_VBottom; break;
+ }
+
+ double kerning = getDoubleValue();
+ double leading = getDoubleValue();
+ double size = getDoubleValue();
+
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+
+ const QString &fontname = elem2.toReference();
+
+ if (m_textHandler) m_textHandler->gotFontDefinition (fontname.latin1(), size, leading, kerning, ta);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleTextBlock (TextOperation to) {
+ AIElement elem (m_stack.top());
+ qDebug ("to element is (%s)",elem.typeName());
+ m_stack.pop();
+
+ const QValueVector<AIElement> aval = elem.toElementArray();
+
+ if (m_textHandler) m_textHandler->gotTextBlockBegin (aval, to);
+} */
+
+/*Ai88*/ /* void AIParserBase::_handleTextOutput () {
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+
+ const QString &text = elem.toString();
+
+ int length = -1;
+
+ if (m_stack.empty())
+ {
+ AIElement elem2 (m_stack.top());
+ if (elem2.type() == AIElement::Int)
+ {
+ length = elem2.asInt();
+ m_stack.pop();
+ }
+ }
+ if (m_textHandler) m_textHandler->gotTextOutput (text.latin1(), length);
+} */
+
+void AIParserBase::_handleCreationDate (const char *data)
+{
+ if (!data) return;
+
+ QRegExp test ("\\((.+)\\) \\((.+)\\)");
+ if (test.search (data))
+ {
+ QString val1 = test.cap(1);
+ QString val2 = test.cap(2);
+
+ if (m_documentHandler) m_documentHandler->gotCreationDate (val1.latin1(),val2.latin1());
+ }
+}
+
+void AIParserBase::gotToken (const char *value) {
+ if (m_debug) qDebug ("got token");
+
+ if (m_ignoring) return;
+ if (m_debug) qDebug ("token: %s", value);
+
+ if (m_sink == DS_Array)
+ {
+ if (m_debug) qDebug ("token in array");
+ QString op (value);
+ AIElement realElement (op, AIElement::Operator);
+ handleElement (realElement);
+
+ return;
+ }
+ if (m_sink == DS_Block)
+ {
+ if (m_debug) qDebug ("token in block");
+ QString op (value);
+ AIElement realElement (op, AIElement::Operator);
+ handleElement (realElement);
+
+ return;
+ }
+
+ if (m_debug) qDebug ("get ai operation");
+
+ AIOperation op = getAIOperation (value);
+// PathElement pathElement;
+// double fval;
+// int ival;
+
+ bool handled = false;
+
+ handled = m_ai88Handler->handleAIOperation (op);
+ if (!handled) handled = m_ai3Handler->handleAIOperation (op);
+
+ if (!handled)
+ {
+ if (m_sink == DS_Other)
+ {
+ if (handlePS (value)) return;
+ }
+ qWarning ( "unknown operator: %s", value );
+
+ QString string(value);
+
+ if (m_modules.findIndex(string) != -1)
+ {
+ AIElement element (string, AIElement::Reference);
+ handleElement (element);
+ return;
+ }
+
+ if (m_debug) stacktoa (m_stack);
+ qWarning ( "pushing %s to stack", value );
+ AIElement element (string, AIElement::Operator);
+ handleElement (element);
+ }
+
+ if (m_debug) qDebug ("/got token value");
+}
+
+bool AIParserBase::handlePS (const char *operand){
+ if (m_ignoring) return false;
+
+ PSOperation psop = getPSOperation (operand);
+
+ switch (psop)
+ {
+ case PSO_Get :
+ _handlePSGet ();
+ return true;
+ case PSO_Exec :
+ _handlePSExec ();
+ return true;
+ case PSO_Def :
+ _handlePSDef ();
+ return true;
+ case PSO_String :
+ _handlePSString ();
+ return true;
+ case PSO_Bind :
+ _handlePSBind ();
+ return true;
+ case PSO_Userdict :
+ _handlePSUserdict ();
+ return true;
+ case PSO_Dict :
+ _handlePSDict ();
+ return true;
+ case PSO_Dup :
+ _handlePSDup ();
+ return true;
+ case PSO_Begin :
+ _handlePSBegin ();
+ return true;
+ case PSO_Put :
+ _handlePSPut ();
+ return true;
+ default: break;
+ }
+ return false;
+}
+
+const double AIParserBase::getDoubleValue(void) {
+ const AIElement &elem = m_stack.pop();
+
+ return elem.toDouble();
+}
+
+const int AIParserBase::getIntValue(void) {
+ const AIElement &elem = m_stack.pop();
+
+ return elem.toInt();
+}
+
+const bool AIParserBase::getBoolValue(void) {
+ return getIntValue() == 1;
+}
+
+const QString AIParserBase::getStringValue(void) {
+ const AIElement &elem = m_stack.pop();
+
+ return elem.toString();
+}
+
+const QString AIParserBase::getOperatorValue(void) {
+ const AIElement &elem = m_stack.pop();
+
+ return elem.toOperator();
+}
+
+AIOperation AIParserBase::getAIOperation (const char *operand)
+{
+ int i=0;
+ QString cmpValue (operand);
+
+ for(;;) { AIOperationMapping map = aiMappings[i];
+ if (map.op == NULL) return AIO_Other;
+ if (cmpValue.compare (map.op) == 0) return map.action;
+
+ i++;
+ }
+}
+
+PSOperation AIParserBase::getPSOperation (const char *operand)
+{
+ int i=0;
+ QString cmpValue (operand);
+
+ for(;;) { PSOperationMapping map = psMappings[i];
+ if (map.op == NULL) return PSO_Other;
+ if (cmpValue.compare (map.op) == 0) return map.action;
+
+ i++;
+ }
+}
+
+CommentOperation AIParserBase::getCommentOperation (const char *command) {
+ QString data (command);
+
+ signed int index;
+
+ int i=0;
+
+ for(;;) {
+ CommentOperationMapping map = commentMappings[i];
+ if (map.op == NULL) return CO_Other;
+ index = data.find (map.op);
+ if (index >= 0) return map.action;
+ i++;
+ }
+}
+
+void GStateHandlerBase::gotFillPattern (const char *pname, double px, double py, double sx, double sy, double angle, double rf, double r, double k, double ka, const QValueVector<AIElement>& transformData) {
+ qDebug ( "got fill pattern %s %f %f %f %f %f %f %f %f %f", pname, px, py, sx, sy, angle, rf, r, k, ka);
+ arraytoa (transformData);
+ qDebug ("/got fill pattern");
+}
+
+void GStateHandlerBase::gotStrokePattern (const char *pname, double px, double py, double sx, double sy, double angle, double rf, double r, double k, double ka, const QValueVector<AIElement>& transformData) {
+ qDebug ( "got stroke pattern %s %f %f %f %f %f %f %f %f %f", pname, px, py, sx, sy, angle, rf, r, k, ka);
+ arraytoa (transformData);
+ qDebug ("/got stroke pattern");
+}
+
+const char *AIParserBase::getValue (const char *input) {
+ QString data(input);
+
+ signed int index = data.find (':');
+ if (index < 0) return "";
+ index++;
+ while (data.at(index) == ' ') index++;
+ return data.mid(index).latin1();
+}
+
+bool AIParserBase::getRectangle (const char* input, int &llx, int &lly, int &urx, int &ury) {
+ if (input == NULL) return false;
+
+ QString s(input);
+ if (s.contains ("(atend)")) return false;
+ QStringList values = QStringList::split (" ", input);
+ if (values.size() < 5) return false;
+ llx = values[1].toInt();
+ lly = values[2].toInt();
+ urx = values[3].toInt();
+ ury = values[4].toInt();
+
+ return true;
+}
+
+bool AIParserBase::getPoint (const char* input, int &x, int &y) {
+ if (input == NULL) return false;
+
+ QString s(input);
+ QStringList values = QStringList::split (" ", input);
+
+ if (values.size() < 3) return false;
+
+ x = values[1].toInt();
+ y = values[2].toInt();
+
+ return true;
+}
+
+void AIParserBase::cleanupArrays()
+{
+ if (m_sink == DS_Array) qDebug ("unclosed array(s).");
+ while (m_sink == DS_Array) gotArrayEnd ();
+ stacktoa (m_stack);
+}
+
+/*Ai88*/ /* void AIParserBase::_handleFontEncoding()
+{
+ while (m_stack.top().type() != AIElement::Reference) {
+ m_stack.pop();
+ }
+
+ AIElement elem (m_stack.top());
+ m_stack.pop();
+ const QString &oldFont = elem.toReference();
+
+ AIElement elem2 (m_stack.top());
+ m_stack.pop();
+ const QString &newFont = elem2.toReference();
+
+ AIElement elem3 (m_stack.top());
+ m_stack.pop();
+ const QValueVector<AIElement> encodingData = elem3.toElementArray();
+
+ if (m_textHandler) m_textHandler->gotFontEncoding (encodingData, oldFont.latin1(), newFont.latin1());
+} */
+
+void TextHandlerBase::gotFontEncoding (const QValueVector<AIElement>& encodingData, const char*oldFontName, const char*newFontName)
+{
+ qDebug ("font encoding %s to %s",oldFontName, newFontName);
+ arraytoa (encodingData);
+ qDebug ("/font encoding");
+}
+
+void TextHandlerBase::gotFontDefinition (const char*fontName, double size, double leading, double kerning, TextAlign align)
+{
+ qDebug ("font definition: name %s size %f leading %f kerning %f align %d", fontName, size, leading, kerning, align);
+}
+
+void TextHandlerBase::gotTextBlockBegin (const QValueVector<AIElement>& transData, TextOperation mode)
+{
+ qDebug ("text block begin %d",mode);
+ arraytoa (transData);
+ qDebug ("/text block begin");
+}
+
+void TextHandlerBase::gotTextOutput (const char*text, int length)
+{
+ qDebug ("text output (%s) %d",text,length);
+}
+
+void TextHandlerBase::gotTextBlockEnd ()
+{
+ qDebug ("text block end");
+}
+
+const void elementtoa (const AIElement &/*data*/)
+{
+/* AIElement::Type type = data.type();
+ qDebug ("type: %s", AIElement::typeToName (type));
+
+ switch (type)
+ {
+ case AIElement::String :
+ case AIElement::CString :
+ case AIElement::Int :
+ case AIElement::UInt :
+ case AIElement::Double :
+ qDebug ("string value : %s",data.toString().latin1());
+ break;
+ case AIElement::Reference :
+ qDebug ("string value : %s",data.toReference().latin1());
+ break;
+ case AIElement::Operator :
+ qDebug ("string value : %s",data.toOperator().latin1());
+ break;
+ case AIElement::ElementArray :
+ arraytoa (data.toElementArray());
+ break;
+ case AIElement::Block :
+ arraytoa (data.toBlock());
+ break;
+
+ default :
+ qDebug ("could not fetch data");
+ } */
+}
+
+const void arraytoa (const QValueVector<AIElement> &/*data*/)
+{
+/* qDebug ("array size is %d ",data.size());
+ if (data.size() > 0)
+ {
+ qDebug ("[[[[[[[[[[[[[[[[[[[[");
+ for (uint i=0; i< data.size(); i++)
+ {
+ elementtoa (data[i]);
+ }
+ qDebug ("]]]]]]]]]]]]]]]]]]]]");
+ } */
+}
+
+const void stacktoa (const QValueStack<AIElement> &/*data*/)
+{
+/* qDebug ("stack size is %d",data.size());
+ if (data.size() > 0)
+ {
+ qDebug ("<<<<<<<<<<<<<<<<<<");
+ for (uint i=0; i< data.size(); i++)
+ {
+ elementtoa (data[i]);
+ }
+ }
+ qDebug (">>>>>>>>>>>>>>>>>>"); */
+}
+
+const void stacktoa2 (const QValueStack<QValueVector<AIElement> >&/*data*/)
+{
+/* qDebug ("stack size is %d",data.size());
+
+ if (data.size() > 0)
+ {
+ qDebug ("(((((((((((((((((((((((");
+ for (uint i=0; i< data.size(); i++)
+ {
+ arraytoa (data[i]);
+ }
+ qDebug (")))))))))))))))))))))))");
+ } */
+}
+
+const void aiotoa (AIOperation &data)
+{
+ switch (data)
+ {
+ case AIO_SetFillColorCMYK : qDebug ("AIO_SetFillColorCMYK"); break;
+ case AIO_SetStrokeColorCMYK : qDebug ("AIO_SetStrokeColorCMYK"); break;
+ case AIO_SetFillColorGray : qDebug ("AIO_SetFillColorGray"); break;
+ case AIO_SetStrokeColorGray : qDebug ("AIO_SetStrokeColorGray"); break;
+ case AIO_SetFillColorCustom : qDebug ("AIO_SetFillColorCustom"); break;
+ case AIO_SetStrokeColorCustom : qDebug ("AIO_SetStrokeColorCustom"); break;
+ case AIO_SetFillPattern : qDebug ("AIO_SetFillPattern"); break;
+ case AIO_SetStrokePattern : qDebug ("AIO_SetStrokePattern"); break;
+ case AIO_SetFillOverprinting : qDebug ("AIO_SetFillOverprinting"); break;
+ case AIO_SetStrokeOverprinting : qDebug ("AIO_SetStrokeOverprinting"); break;
+ case AIO_SetFlatness : qDebug ("AIO_SetFlatness"); break;
+ case AIO_SetLineCap : qDebug ("AIO_SetLineCap"); break;
+ case AIO_SetLineJoin : qDebug ("AIO_SetLineJoin"); break;
+ case AIO_SetLineWidth : qDebug ("AIO_SetLineWidth"); break;
+ case AIO_SetMiterLimit : qDebug ("AIO_SetMiterLimit"); break;
+ case AIO_SetDash : qDebug ("AIO_SetDash"); break;
+ case AIO_BeginGroupClip : qDebug ("AIO_BeginGroupClip"); break;
+ case AIO_EndGroupClip : qDebug ("AIO_EndGroupClip"); break;
+ case AIO_MoveTo : qDebug ("AIO_MoveTo"); break;
+ case AIO_LineToCorner : qDebug ("AIO_LineToCorner"); break;
+ case AIO_LineToSmooth : qDebug ("AIO_LineToSmooth"); break;
+ case AIO_CurveToSmooth : qDebug ("AIO_CurveToSmooth"); break;
+ case AIO_CurveToCorner : qDebug ("AIO_CurveToCorner"); break;
+ case AIO_CurveToOmitC1Smooth : qDebug ("AIO_CurveToOmitC1Smooth"); break;
+ case AIO_CurveToOmitC1Corner : qDebug ("AIO_CurveToOmitC1Corner"); break;
+ case AIO_CurveToOmitC2Smooth : qDebug ("AIO_CurveToOmitC2Smooth"); break;
+ case AIO_CurveToOmitC2Corner : qDebug ("AIO_CurveToOmitC2Corner"); break;
+ case AIO_PathIgnoreNoReset : qDebug ("AIO_PathIgnoreNoReset"); break;
+ case AIO_PathIgnoreNoResetClose : qDebug ("AIO_PathIgnoreNoResetClose"); break;
+ case AIO_PathClipPath : qDebug ("AIO_PathClipPath"); break;
+ case AIO_PathIgnoreReset : qDebug ("AIO_PathIgnoreReset"); break;
+ case AIO_PathIgnoreResetClose : qDebug ("AIO_PathIgnoreResetClose"); break;
+ case AIO_PathFillNonZero : qDebug ("AIO_PathFillNonZero"); break;
+ case AIO_PathFillNonZeroClose : qDebug ("AIO_PathFillNonZeroClose"); break;
+ case AIO_PathStroke : qDebug ("AIO_PathStroke"); break;
+ case AIO_PathStrokeClose : qDebug ("AIO_PathStrokeClose"); break;
+ case AIO_PathFillNoReset : qDebug ("AIO_PathFillNoReset"); break;
+ case AIO_PathFillNoResetClose : qDebug ("AIO_PathFillNoResetClose"); break;
+ case AIO_FontEncoding : qDebug ("AIO_FontEncoding"); break;
+ case AIO_PatternDefinition : qDebug ("AIO_PatternDefinition"); break;
+ case AIO_SetCurrentText : qDebug ("AIO_SetCurrentText"); break;
+ case AIO_TextBlockFillStroke : qDebug ("AIO_TextBlockFillStroke"); break;
+ case AIO_TextBlockFill : qDebug ("AIO_TextBlockFill"); break;
+ case AIO_TextBlockAppend : qDebug ("AIO_TextBlockAppend"); break;
+ case AIO_TextBlockIgnore : qDebug ("AIO_TextBlockIgnore"); break;
+ case AIO_TextBlockStroke : qDebug ("AIO_TextBlockStroke"); break;
+ case AIO_TextOutput : qDebug ("AIO_TextOutput"); break;
+ case AIO_TextBlockEnd : qDebug ("AIO_TextBlockEnd"); break;
+ case AIO_GsaveIncludeDocument : qDebug ("AIO_GsaveIncludeDocument"); break;
+ case AIO_Grestore : qDebug ("AIO_Grestore"); break;
+ case AIO_LockElement : qDebug ("AIO_LockElement"); break;
+ case AIO_SetWindingOrder : qDebug ("AIO_SetWindingOrder"); break;
+ default : qDebug ("unknown");
+ }
+}
+
+const void sttoa (SectionType &data, bool begin)
+{
+ switch (data)
+ {
+ case ST_Setup : begin ? qDebug ("start setup") : qDebug ("end setup"); break;
+ case ST_Prolog : begin ? qDebug ("start prolog") : qDebug ("end prolog"); break;
+ case ST_ProcSet : begin ? qDebug ("start procset") : qDebug ("end procset"); break;
+ case ST_Encoding : begin ? qDebug ("start encoding") : qDebug ("end encoding"); break;
+ case ST_Pattern : begin ? qDebug ("start pattern") : qDebug ("end pattern"); break;
+ case ST_Document : begin ? qDebug ("start document") : qDebug ("end document"); break;
+ case ST_BrushPattern : begin ? qDebug ("start brush pattern") : qDebug ("end brush pattern"); break;
+ case ST_Gradient : begin ? qDebug ("start gradient") : qDebug ("end gradient"); break;
+ case ST_Palette : begin ? qDebug ("start palette") : qDebug ("end palette"); break;
+ case ST_Resource : begin ? qDebug ("start resource") : qDebug ("end resouce"); break;
+
+ default : begin ? qDebug ("unknown") : qDebug ("end unknown");
+ }
+}
+
diff --git a/filters/karbon/ai/aiparserbase.h b/filters/karbon/ai/aiparserbase.h
new file mode 100644
index 00000000..8d2633f3
--- /dev/null
+++ b/filters/karbon/ai/aiparserbase.h
@@ -0,0 +1,440 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schönberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef AIPARSERBASE_H
+#define AIPARSERBASE_H
+
+#include "ailexer.h"
+
+#include <qstring.h>
+#include <qvaluestack.h>
+#include <qvaluevector.h>
+#include <qvaluelist.h>
+
+#include "aielement.h"
+#include "aicolor.h"
+
+
+const void arraytoa (const QValueVector<AIElement> &data);
+const void elementtoa (const AIElement &data);
+const void stacktoa (const QValueStack<AIElement> &data);
+const void stacktoa2 (const QValueStack<QValueVector<AIElement> >&data);
+
+class GStateHandlerBase;
+class StructureHandlerBase;
+class PathHandlerBase;
+class MiscGStateHandlerBase;
+class DocumentHandlerBase;
+class ModuleHandlerBase;
+class EmbeddedHandlerBase;
+class TextHandlerBase;
+class AI88Handler;
+class AI3Handler;
+
+/**
+ *@author Dirk Schönberger
+ */
+
+typedef enum { PET_MoveTo, PET_LineTo, PET_CurveTo, PET_CurveToOmitC1, PET_CurveToOmitC2 } PathElementType;
+typedef enum { PT_Smooth, PT_Corner } PointType;
+typedef enum { TO_FillStroke, TO_Fill, TO_Append, TO_Ignore, TO_Stroke } TextOperation;
+typedef enum { FM_NonZero=0, FM_EvenOdd=1 } FillMode;
+typedef enum { FS_Roman, FS_Kanji } FontScript;
+
+typedef enum { DS_Array, DS_Block, DS_Other } DataSink;
+typedef enum { ST_Setup, ST_Prolog, ST_ProcSet, ST_Encoding, ST_Pattern, ST_Document, ST_BrushPattern, ST_Gradient, ST_Palette, ST_Resource } SectionType;
+
+typedef enum { TA_HLeft, TA_HCenter, TA_HRight, TA_VTop, TA_VCenter, TA_VBottom } TextAlign;
+
+#define PC_Cyan 0x0001
+#define PC_Magenta 0x0002
+#define PC_Yellow 0x0004
+#define PC_Black 0x0008
+
+typedef enum {
+ /* AI 88 */
+ AIO_SetFillColorCMYK, AIO_SetStrokeColorCMYK,
+ AIO_SetFillColorGray, AIO_SetStrokeColorGray,
+ AIO_SetFillColorCustom, AIO_SetStrokeColorCustom,
+ AIO_SetFillPattern, AIO_SetStrokePattern,
+ AIO_SetFillOverprinting, AIO_SetStrokeOverprinting,
+ AIO_SetFlatness, AIO_SetLineCap, AIO_SetLineJoin,
+ AIO_SetLineWidth, AIO_SetMiterLimit, AIO_SetDash,
+ AIO_BeginGroupClip, AIO_EndGroupClip,
+ AIO_MoveTo,
+ AIO_LineToCorner,
+ AIO_LineToSmooth,
+ AIO_CurveToSmooth,
+ AIO_CurveToCorner,
+ AIO_CurveToOmitC1Smooth,
+ AIO_CurveToOmitC1Corner,
+ AIO_CurveToOmitC2Smooth,
+ AIO_CurveToOmitC2Corner,
+
+ AIO_PathIgnoreNoReset, AIO_PathIgnoreNoResetClose,
+ AIO_PathClipPath,
+ AIO_PathIgnoreReset, AIO_PathIgnoreResetClose,
+ AIO_PathFillNonZero, AIO_PathFillNonZeroClose,
+ AIO_PathStroke, AIO_PathStrokeClose,
+ AIO_PathFillNoReset, AIO_PathFillNoResetClose,
+
+ AIO_FontEncoding,
+ AIO_PatternDefinition,
+
+ AIO_SetCurrentText,
+ AIO_TextBlockFillStroke,
+ AIO_TextBlockFill,
+ AIO_TextBlockAppend,
+ AIO_TextBlockIgnore,
+ AIO_TextBlockStroke,
+ AIO_TextOutput,
+ AIO_TextBlockEnd,
+
+ AIO_GsaveIncludeDocument,
+ AIO_Grestore,
+
+ AIO_LockElement,
+
+ /* AI 3 */
+ AIO_SetWindingOrder,
+ AIO_SetFillMode,
+
+ AIO_BeginGroupNoClip, AIO_EndGroupNoClip,
+ AIO_BeginCombination, AIO_EndCombination,
+
+ AIO_Other
+} AIOperation;
+
+typedef enum {
+ PSO_Get,
+ PSO_Exec,
+ PSO_Def,
+ PSO_String,
+ PSO_Bind,
+ PSO_Userdict,
+ PSO_Dict,
+ PSO_Dup,
+ PSO_Begin,
+ PSO_Put,
+ PSO_Other
+} PSOperation;
+
+typedef enum {
+ CU_BlackWhite,
+ CU_Color,
+ CU_Unknown
+} ColorUsage;
+
+typedef enum {
+ CO_BeginSetup, CO_EndSetup,
+ CO_BeginProlog, CO_EndProlog,
+ CO_BeginProcSet, CO_EndProcSet,
+ CO_BeginEncoding, CO_EndEncoding,
+ CO_BeginPattern, CO_EndPattern,
+ CO_IncludeFile,
+ CO_BeginDocument, CO_EndDocument,
+
+ CO_Trailer,
+ CO_BoundingBox,
+ CO_TemplateBox,
+ CO_Margin,
+ CO_Title,
+ CO_Creator,
+ CO_Other,
+/**/ CO_For,
+ CO_CreationDate,
+/**/ CO_DocumentFonts,
+/**/ CO_DocumentFiles,
+/**/ CO_ColorUsage,
+/**/ CO_DocumentProcSets,
+/**/ CO_DocumentSuppliedProcSets,
+ CO_DocumentProcessColors,
+/**/ CO_DocumentCustomColors,
+/**/ CO_CMYKCustomColor,
+/**/ CO_TileBox,
+ CO_Continuation,
+/**/ CO_Note,
+
+ // AI88 Win
+/**/ CO_Template,
+/**/ CO_PageOrigin,
+/**/ CO_PrinterName,
+/**/ CO_PrinterRect,
+
+ // AI8
+ CO_BeginBrushPattern, CO_EndBrushPattern,
+ CO_BeginGradient, CO_EndGradient,
+ CO_BeginPalette, CO_EndPalette,
+
+ // other
+ CO_BeginResource, CO_EndResource,
+ CO_IncludeFont,
+ CO_IncludeResource,
+ CO_DocumentNeededResources,
+
+ CO_Ignore
+} CommentOperation;
+
+typedef enum {
+ CM_DocumentFonts = 1,
+ CM_DocumentFiles = 2,
+ CM_DocumentCustomColors = 3,
+ CM_CMYKCustomColor = 4,
+ CM_DocumentNeededResources = 5,
+ CM_None = -1
+} ContinuationMode;
+
+typedef enum {
+/**/ PDO_ColorDefinition,
+/**/ PDO_TileDefinition
+} PatternDefinitionOperation;
+
+/**/
+#define PatternTileFilledDefiniton "_"
+#define TextSizeUnknown -1
+
+/* typedef QValueVector<AElement> ElementArray;
+typedef QValueStack<AIElement> ElementStack;
+typedef QValueStack<ElementArray> ElementArrayStack; */
+
+typedef struct {
+ PathElementType petype;
+ union {
+ struct {
+ float x, y;
+ } pointdata;
+ struct {
+ float x1, y1, x2, y2, x3, y3;
+ } bezierdata;
+ } pevalue;
+ PointType pttype;
+} PathElement;
+
+class AIParserBase : protected AILexer {
+ friend class AI88Handler;
+ friend class AI3Handler;
+
+protected:
+ bool m_debug;
+private:
+ bool m_ignoring;
+ QValueStack<AIElement> m_stack;
+ QValueStack<QValueVector<AIElement> > m_arrayStack;
+ QValueStack<QValueVector<AIElement> > m_blockStack;
+ DataSink m_sink;
+ QValueList<QString> m_modules;
+ ContinuationMode m_continuationMode;
+
+ const double getDoubleValue(void);
+ const int getIntValue(void);
+ const bool getBoolValue(void);
+ const QString getStringValue(void);
+ const QString& getReferenceValue(void);
+ const QString getOperatorValue(void);
+
+/*Ai88*/ // void _handleSetDash();
+/*Ai88*/ // void _handleGsaveIncludeDocument();
+/*Ai88*/ // void _handleSetStrokeColorCMYK();
+/*Ai88*/ // void _handleSetFillColorCMYK();
+/*Ai88*/ // void _handleSetStrokeColorGray();
+/*Ai88*/ // void _handleSetFillColorGray();
+/*Ai88*/ // void _handleSetStrokeColorCustom();
+/*Ai88*/ // void _handleSetFillColorCustom();
+/*Ai88*/ // void _handleSetFillPattern();
+/*Ai88*/ // void _handleSetStrokePattern();
+
+/*Ai88*/ // void _handlePatternDefinition();
+/*Ai88*/ // void _handleFontEncoding();
+
+ void _handlePSGet();
+ void _handlePSExec();
+ void _handlePSDef();
+ void _handlePSString();
+ void _handlePSBind();
+ void _handlePSUserdict();
+ void _handlePSDict();
+ void _handlePSDup();
+ void _handlePSBegin();
+ void _handlePSPut();
+
+ void _handleDocumentFonts(const char *data);
+ void _handleDocumentFiles(const char *data);
+ void _handleDocumentCustomColors(const char *data);
+ void _handleCMYKCustomColor(const char *data);
+ void _handleDocumentProcessColors(const char *data);
+ void _handleDocumentNeededResources(const char *data);
+ void _handleIncludeResource(const char *data);
+
+/*Ai88*/ // void _handleSetCurrentText();
+/*Ai88*/ // void _handleTextBlock (TextOperation to);
+/*Ai88*/ // void _handleTextOutput ();
+
+ void _handleCreationDate (const char *data);
+
+ AIOperation getAIOperation (const char *operand);
+ PSOperation getPSOperation (const char *operand);
+ CommentOperation getCommentOperation (const char *command);
+
+ bool handlePS (const char *operand);
+
+ const char *getValue (const char *input);
+ bool getRectangle (const char* input, int &llx, int &lly, int &urx, int &ury);
+ bool getPoint (const char* input, int &x, int &y);
+protected:
+ void gotComment (const char *value);
+ void gotIntValue (int value);
+ void gotDoubleValue (double value);
+ void gotStringValue (const char *value);
+ void gotToken (const char *value);
+ void gotReference (const char *value);
+ void gotBlockStart ();
+ void gotBlockEnd ();
+ void gotArrayStart ();
+ void gotArrayEnd ();
+ void gotByte (uchar value);
+ void gotByteArray (const QByteArray &data);
+
+ GStateHandlerBase *m_gstateHandler;
+ StructureHandlerBase *m_structureHandler;
+ PathHandlerBase *m_pathHandler;
+ MiscGStateHandlerBase *m_miscGStateHandler;
+ DocumentHandlerBase *m_documentHandler;
+ ModuleHandlerBase *m_moduleHandler;
+ EmbeddedHandlerBase *m_embeddedHandler;
+ TextHandlerBase *m_textHandler;
+ AI88Handler *m_ai88Handler;
+ AI3Handler *m_ai3Handler;
+
+private:
+ void handleElement (AIElement &element);
+ void cleanupArrays();
+public:
+ AIParserBase();
+ ~AIParserBase();
+
+ bool parse (QIODevice& fin);
+};
+
+const void aiotoa (AIOperation &data);
+const void sttoa (SectionType &data, bool begin);
+
+class GStateHandlerBase
+{
+ public:
+ GStateHandlerBase() {}
+ virtual ~GStateHandlerBase() {}
+
+ virtual void gotFillColor (AIColor &) {}
+ virtual void gotStrokeColor (AIColor &) {}
+ virtual void gotFillPattern (const char *pname, double px, double py, double sx, double sy, double angle, double rf, double r, double k, double ka, const QValueVector<AIElement>& transformData);
+ virtual void gotStrokePattern (const char *pname, double px, double py, double sx, double sy, double angle, double rf, double r, double k, double ka, const QValueVector<AIElement>& transformData);
+ virtual void gotFlatness (double) {}
+ virtual void gotLineWidth (double) {}
+ virtual void gotLineCaps (int) {}
+ virtual void gotLineJoin (int) {}
+ virtual void gotMiterLimit (double) {}
+ virtual void gotWindingOrder (int) {}
+ virtual void gotDash (const QValueVector<AIElement>& /*dashData*/, double /*phase*/) {}
+};
+
+class StructureHandlerBase {
+ public:
+ StructureHandlerBase() {}
+ virtual ~StructureHandlerBase() {}
+
+ virtual void gotBeginGroup (bool /*clipping*/) {}
+ virtual void gotEndGroup (bool /*clipping*/) {}
+ virtual void gotBeginCombination () {}
+ virtual void gotEndCombination () {}
+};
+
+class PathHandlerBase {
+ public:
+ PathHandlerBase() {}
+ virtual ~PathHandlerBase() {}
+
+ virtual void gotPathElement (PathElement &) {}
+ virtual void gotFillPath (bool /*closed*/, bool /*reset*/) {}
+ virtual void gotStrokePath (bool /*closed*/) {}
+ virtual void gotIgnorePath (bool /*closed*/, bool /*reset*/) {}
+ virtual void gotClipPath (bool /*closed*/) {}
+ virtual void gotFillMode (FillMode) {}
+};
+
+class MiscGStateHandlerBase {
+ public:
+ MiscGStateHandlerBase() {}
+ virtual ~MiscGStateHandlerBase() {}
+
+ virtual void gotLockNextObject (bool /*value*/) {}
+ virtual void gotFillOverprinting (bool /*value*/) {}
+ virtual void gotStrokeOverprinting (bool /*value*/) {}
+};
+
+class DocumentHandlerBase {
+ public:
+ DocumentHandlerBase() {}
+ virtual ~DocumentHandlerBase() {}
+
+ virtual void gotBoundingBox (int /*llx*/, int /*lly*/, int /*urx*/, int /*ury*/) {}
+ virtual void gotTemplateBox (int /*llx*/, int /*lly*/, int /*urx*/, int /*ury*/) {}
+ virtual void gotMargin (int /*llx*/, int /*lly*/, int /*urx*/, int /*ury*/) {}
+ virtual void gotPrinterRect (int /*llx*/, int /*lly*/, int /*urx*/, int /*ury*/) {}
+ virtual void gotPrinterName (const char *) {}
+ virtual void gotPageOrigin (int /*x*/, int /*y*/) {}
+ virtual void gotTemplate (const char *) {}
+ virtual void gotTitle (const char *) {}
+ virtual void gotCreator (const char *) {}
+ virtual void gotPatternDefinition (const char */*name*/, const QValueVector<AIElement>& /*layerData*/, double /*llx*/, double /*lly*/, double /*urx*/, double /*ury*/) {}
+ virtual void gotCreationDate (const char */*val1*/,const char */*val2*/) {}
+ virtual void gotProcessColors (int /*colors*/) {}
+};
+
+class ModuleHandlerBase {
+ public:
+ ModuleHandlerBase() {}
+ virtual ~ModuleHandlerBase() {}
+
+ virtual void gotBeginSection (SectionType, const char *) {}
+ virtual void gotEndSection (SectionType, const char *) {}
+};
+
+class EmbeddedHandlerBase {
+ public:
+ EmbeddedHandlerBase() {}
+ virtual ~EmbeddedHandlerBase() {}
+
+ virtual void gotGsaveIncludeDocument (const QValueVector<AIElement>& /*transData*/, int /*llx*/, int /*lly*/, int /*urx*/, int /*ury*/, const char*/*fileName*/) {}
+ virtual void gotGrestore () {}
+};
+
+class TextHandlerBase {
+ public:
+ TextHandlerBase() {}
+ virtual ~TextHandlerBase() {}
+
+ virtual void gotFontEncoding (const QValueVector<AIElement>& encodingData, const char*oldFontName, const char*newFontName);
+ virtual void gotFontDefinition (const char*fontName, double size, double leading, double kerning, TextAlign align);
+ virtual void gotTextBlockBegin (const QValueVector<AIElement>& transData, TextOperation mode);
+ virtual void gotTextOutput (const char*text, int length=-1);
+ virtual void gotTextBlockEnd ();
+};
+
+#endif
+
diff --git a/filters/karbon/ai/karbon_ai_import.desktop b/filters/karbon/ai/karbon_ai_import.desktop
new file mode 100644
index 00000000..bec797b2
--- /dev/null
+++ b/filters/karbon/ai/karbon_ai_import.desktop
@@ -0,0 +1,67 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon14 Illustrator Import Filter
+Name[af]=Karbon14 Illustreerder In voer Filter
+Name[ar]=مِرْشَح استيراد Illustrator لدى Karbon14
+Name[bg]=Филтър за импортиране от Illustrator в Karbon14
+Name[br]=Sil enporzh Illustrator evit Karbon14
+Name[ca]=Filtre d'importació Illustrator per a Karbon14
+Name[cs]=Importní filtr souborů aplikace Illustrator pro Karbon14
+Name[cy]=Hidlen Fewnforio Illustrator Karbon14
+Name[da]=Karbon14 Illustrator-importfilter
+Name[de]=Karbon14 Illustrator-Importfilter
+Name[el]=Φίλτρο εισαγωγής Illustrator του Karbon14
+Name[eo]=Importfiltrilo por Karbon-Ilustrilo
+Name[es]=Filtro de importación Karbon14 Illustrator
+Name[et]=Karbon14 Illustrator'i impordifilter
+Name[eu]=Karbon14 ilustratzailearen inportaziorako iragazkia
+Name[fa]=پالایۀ واردات تصویرگر Karbon14
+Name[fi]=Karbon14 Illustrator -tuontisuodin
+Name[fr]=Filtre d'importation Illustrator vers Karbon 14
+Name[fy]=Illustrator-Ymportfilter foar Karbon14
+Name[ga]=Scagaire Iompórtála Karbon14 Illustrator
+Name[gl]=Filtro de Importación de Illustrator para Karbon14
+Name[he]=מסנן ייבוא מ־Illustrator ל־Karbon14
+Name[hi]=कार्बन 14 इलस्ट्रेटर आयात छननी
+Name[hr]=Karbon14 Illustrator filtar uvoza
+Name[hu]=Karbon14 Illustrator importszűrő
+Name[is]=Karbon14 Illustrator innflutningssía
+Name[it]=Filtro di importazione Illustrator per Karbon14
+Name[ja]=Karbon14 Illustrator インポートフィルタ
+Name[km]=តម្រង​នាំចូល​វិចិត្រសាល​សម្រាប់ Karbon ១៤
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ Illustrator
+Name[lt]=Karbon14 Illustrator importavimo filtras
+Name[lv]=Karbon14 Ilustratora importa filtrs
+Name[ms]=Penapis Import Karbon14 Illustrator
+Name[mt]=Filtru għall-importazzjoni Illustrator għal Karbon14
+Name[nb]=Illustrator-importfilter for Karbon14
+Name[nds]=Illustrator-Importfilter för Karbon14
+Name[ne]=कार्बन१४ ब्याख्याकर्ता आयात फिल्टर
+Name[nl]=Illustrator-importfilter voor Karbon14
+Name[nn]=Illustrator-importfilter for Karbon14
+Name[pl]=Filtr importu formatu Illustrator do Karbon14
+Name[pt]=Filtro de Importação de Illustrator para o Karbon14
+Name[pt_BR]=Filtro de Importação Illustrator do Karbon14
+Name[ro]=Filtru importare Karbon14 pentru Illustrator
+Name[ru]=Фильтр импорта файлов Illustrator в Karbon14
+Name[se]=Karbon14:a Illustrator-sisafievrridansilli
+Name[sk]=Illustrator filter pre import do Karbon14
+Name[sl]=Uvozni filter Illustrator za Karbon14
+Name[sr]=Karbon14-ов филтер за увоз из Illustrator-а
+Name[sr@Latn]=Karbon14-ov filter za uvoz iz Illustrator-a
+Name[sv]=Karbon14 Illustrator-importfilter
+Name[ta]=Karbon 14 Illustrator இறக்குமதி வடிகட்டி
+Name[tg]=Karbon14 EPS Филтри Воридоти Иллюстратор
+Name[th]=ตัวกรองการนำเข้า Illustrator ของคาร์บอน14
+Name[tr]=Karbon14 Illustrator Alma Filtresi
+Name[uk]=Фільтр імпорту Illustrator для Karbon14
+Name[uz]=Karbon14 Illustrator import filteri
+Name[uz@cyrillic]=Karbon14 Illustrator импорт филтери
+Name[xh]=Isihluzi Sokurhweba Somzobi we Karbon 14
+Name[zh_CN]=Karbon14 Illustrator 导入过滤器
+Name[zh_TW]=Karbon14 Illustrator 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=application/illustrator
+X-KDE-Weight=1
+X-KDE-Library=libkarbonaiimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/ai/karbonaiparserbase.cc b/filters/karbon/ai/karbonaiparserbase.cc
new file mode 100644
index 00000000..8c2b5a5f
--- /dev/null
+++ b/filters/karbon/ai/karbonaiparserbase.cc
@@ -0,0 +1,637 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schönberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "karbonaiparserbase.h"
+
+#include <core/vcolor.h>
+#include <core/vlayer.h>
+#include <core/vgroup.h>
+#include <core/vclipgroup.h>
+#include <core/vvisitor.h>
+#include "aicolor.h"
+#include <qwmatrix.h>
+#include <commands/vtransformcmd.h>
+
+#include <KoPageLayout.h>
+
+const void pottoa (PathOutputType &data);
+
+// generic
+KarbonAIParserBase::KarbonAIParserBase() : m_pot(POT_Other), m_ptt (PTT_Output), m_bbox(0,0,612,792), m_emptyFill(), m_emptyStroke()
+/* , m_strokeColor(), m_fillColor() */ {
+
+ // A4, 70 dpi
+/* m_bbox.llx = 0;
+ m_bbox.lly = 0;
+ m_bbox.urx = 612;
+ m_bbox.ury = 792; */
+
+/* m_lineWidth = 0;
+ m_flatness = 0;
+ m_lineCaps = 0;
+ m_lineJoin = 0;
+ m_miterLimit = 10; */
+ m_windingOrder = 0;
+
+ m_fm = FM_NonZero;
+
+ m_curKarbonPath = new VPath( 0L );
+
+ m_document = new VDocument();
+ m_layer = NULL;
+ m_combination = NULL;
+
+ m_emptyFill.setType (VFill::none);
+ m_emptyStroke.setType (VStroke::none);
+
+ setupHandlers();
+}
+
+// generic
+KarbonAIParserBase::~KarbonAIParserBase(){
+ teardownHandlers();
+ delete m_curKarbonPath;
+
+ delete m_document;
+}
+
+// generic
+void KarbonAIParserBase::parsingStarted(){
+// qDebug ( getHeader().latin1() );
+}
+
+// generic
+void KarbonAIParserBase::parsingFinished(){
+// qDebug ( getFooter().latin1() );
+
+ // handle bounding box
+ if (m_document)
+ {
+ kdDebug() << "bbox 1 is " << m_bbox << endl;
+
+ if (m_bbox.width() > 0. )
+ m_document->setWidth (m_bbox.width());
+ if (m_bbox.height() > 0. )
+ m_document->setHeight (m_bbox.height());
+
+/* QWMatrix matrix;
+ matrix.translate (-m_bbox.x(),-m_bbox.y());
+
+ VTransformNodes translator (matrix);
+ m_document->accept (translator); */
+ VTranslateCmd cmd (0L, -m_bbox.x(), -m_bbox.y());
+ m_document->accept (cmd);
+ }
+}
+
+// generic
+QString KarbonAIParserBase::getParamList(Parameters& params){
+ QString data("");
+
+ Parameter *param;
+
+ if (params.count() > 0)
+ {
+
+ for ( param=params.first(); param != 0; param=params.next() ) {
+ data += " " + param->first + "=\"" + param->second + "\"";
+ }
+ }
+
+ return data;
+}
+
+// generic
+void KarbonAIParserBase::gotStartTag (const char *tagName, Parameters& params){
+ qDebug ("<%s%s>", tagName, getParamList (params).latin1() );
+}
+
+// generic
+void KarbonAIParserBase::gotEndTag (const char *tagName){
+ qDebug ("</%s>", tagName );
+}
+
+// generic
+void KarbonAIParserBase::gotSimpleTag (const char *tagName, Parameters& params){
+ qDebug ("<%s%s/>", tagName, getParamList (params).latin1() );
+}
+
+// generic
+void KarbonAIParserBase::gotPathElement (PathElement &element){
+ switch (element.petype)
+ {
+ case PET_MoveTo :
+ m_curKarbonPath->moveTo (KoPoint (element.pevalue.pointdata.x,element.pevalue.pointdata.y));
+ break;
+ case PET_LineTo :
+ m_curKarbonPath->lineTo (KoPoint (element.pevalue.pointdata.x,element.pevalue.pointdata.y));
+ break;
+ case PET_CurveTo :
+ m_curKarbonPath->curveTo (KoPoint (element.pevalue.bezierdata.x1,element.pevalue.bezierdata.y1),
+ KoPoint (element.pevalue.bezierdata.x2,element.pevalue.bezierdata.y2),
+ KoPoint (element.pevalue.bezierdata.x3,element.pevalue.bezierdata.y3));
+ break;
+ case PET_CurveToOmitC1 :
+ m_curKarbonPath->curve1To (KoPoint (element.pevalue.bezierdata.x2,element.pevalue.bezierdata.y2),
+ KoPoint (element.pevalue.bezierdata.x3,element.pevalue.bezierdata.y3));
+ break;
+ case PET_CurveToOmitC2 :
+ m_curKarbonPath->curve2To (KoPoint (element.pevalue.bezierdata.x1,element.pevalue.bezierdata.y1),
+ KoPoint (element.pevalue.bezierdata.x3,element.pevalue.bezierdata.y3));
+ break;
+ }
+}
+
+// generic
+void KarbonAIParserBase::gotFillPath (bool closed, bool reset, FillMode /*fm*/){
+// qDebug ("found fill path");
+// if (!reset) qDebug ("retain filled path");
+
+ if (closed) m_curKarbonPath->close();
+
+ if (!reset)
+ m_pot = POT_Filled;
+ else
+ {
+ doOutputCurrentPath2 (POT_Filled);
+ m_pot = POT_Other;
+ }
+}
+
+// generic
+void KarbonAIParserBase::gotIgnorePath (bool closed, bool reset){
+// qDebug ("found ignore path");
+
+ if (closed) m_curKarbonPath->close();
+
+ if (! reset)
+ m_pot = POT_Other;
+ else
+ {
+ doOutputCurrentPath2 (POT_Ignore);
+ m_pot = POT_Other;
+ }
+}
+
+// generic
+void KarbonAIParserBase::gotStrokePath (bool closed) {
+// qDebug ("found stroke path");
+
+ if (closed) m_curKarbonPath->close();
+
+ PathOutputType pot = POT_Stroked;
+ if (m_pot != POT_Other)
+ {
+ pot = POT_FilledStroked;
+ }
+
+ doOutputCurrentPath2 (pot);
+
+ m_pot = POT_Other;
+}
+
+// generic
+void KarbonAIParserBase::gotClipPath (bool /*closed*/){
+
+ doOutputCurrentPath2 (POT_Clip);
+}
+
+// generic
+void KarbonAIParserBase::gotFillColor (AIColor &color){
+// double r, g, b;
+// color.toRGB (r,g,b);
+// qDebug ("set fillcolor to %f %f %f",r,g,b);
+// m_fillColor = color;
+
+ VColor karbonColor = toKarbonColor (color);
+ m_fill.setColor (karbonColor);
+}
+
+// generic
+void KarbonAIParserBase::gotStrokeColor (AIColor &color){
+// double r, g, b;
+// color.toRGB (r,g,b);
+// qDebug ("set strokecolor to %f %f %f",r,g,b);
+// m_strokeColor = color;
+
+ VColor karbonColor = toKarbonColor (color);
+ m_stroke.setColor (karbonColor);
+}
+
+// generic
+void KarbonAIParserBase::gotBoundingBox (int llx, int lly, int urx, int ury){
+/* m_bbox.llx = llx;
+ m_bbox.lly = lly;
+ m_bbox.urx = urx;
+ m_bbox.ury = ury; */
+ m_bbox.setCoords(llx,lly,urx,ury);
+}
+
+void KarbonAIParserBase::gotLineWidth (double val){
+// m_lineWidth = val;
+ m_stroke.setLineWidth (val);
+}
+
+void KarbonAIParserBase::gotFlatness (double /*val*/)
+{
+// m_flatness = val;
+// m_stroke.setFlatness (val);
+}
+
+void KarbonAIParserBase::gotLineCaps (int val)
+{
+// m_lineCaps = val;
+ VStroke::VLineCap lineCap = VStroke::capButt;
+
+ switch (val)
+ {
+ case 0 : lineCap = VStroke::capButt; break;
+ case 1 : lineCap = VStroke::capRound; break;
+ case 2 : lineCap = VStroke::capSquare; break;
+ }
+
+ m_stroke.setLineCap (lineCap);
+}
+
+void KarbonAIParserBase::gotLineJoin (int val)
+{
+// m_lineJoin = val;
+
+ VStroke::VLineJoin lineJoin = VStroke::joinMiter;
+
+ switch (val)
+ {
+ case 0 : lineJoin = VStroke::joinMiter; break;
+ case 1 : lineJoin = VStroke::joinRound; break;
+ case 2 : lineJoin = VStroke::joinBevel; break;
+ }
+
+ m_stroke.setLineJoin (lineJoin);
+
+}
+
+void KarbonAIParserBase::gotMiterLimit (double val)
+{
+// m_miterLimit = val;
+ m_stroke.setMiterLimit (val);
+}
+
+void KarbonAIParserBase::gotWindingOrder (int val)
+{
+ m_windingOrder = val;
+}
+
+void KarbonAIParserBase::gotBeginGroup (bool clipping)
+{
+// qDebug ("start begin group");
+ if (clipping)
+ {
+ VClipGroup *group = new VClipGroup( 0L );
+ m_groupStack.push (group);
+ }
+ else
+ {
+ VGroup *group = new VGroup( 0L );
+ m_groupStack.push (group);
+ }
+
+// qDebug ("end begin group");
+
+}
+
+void KarbonAIParserBase::gotEndGroup (bool /*clipping*/)
+{
+// qDebug ("start end group");
+
+ if (m_debug) qDebug ("got end group");
+
+ if (m_groupStack.isEmpty()) return;
+
+ if (m_debug) qDebug ("got end group 2");
+
+ VGroup *group = m_groupStack.pop();
+
+ if (m_debug) qDebug ("got end group 3");
+
+ if (m_debug)
+ {
+ if (!group) qDebug ("group is NULL");
+ }
+
+ if (m_groupStack.isEmpty())
+ {
+ if (m_debug) qDebug ("insert object");
+ ensureLayer();
+ m_layer->append (group);
+ if (m_debug) qDebug ("/insert object");
+ }
+ else
+ {
+ if (m_debug) qDebug ("insert object to group");
+
+ m_groupStack.top()->append (group);
+ if (m_debug) qDebug ("/insert object to group");
+ }
+
+ if (m_debug) qDebug ("/got end group");
+
+// qDebug ("end end group");
+}
+
+void KarbonAIParserBase::gotBeginCombination () {
+ m_ptt = PTT_Combine;
+}
+
+void KarbonAIParserBase::gotEndCombination () {
+// qDebug ( "got end combination" );
+
+ m_ptt = PTT_Output;
+
+ if (m_combination != NULL)
+ {
+ m_curKarbonPath = m_combination;
+ doOutputCurrentPath2 (POT_Leave);
+ }
+
+ m_combination = NULL;
+}
+
+
+const VColor KarbonAIParserBase::toKarbonColor (const AIColor &color)
+{
+ AIColor temp (color);
+ VColor value;
+
+ double v1, v2, v3, v4;
+ temp.toCMYK (v1, v2, v3, v4);
+
+ float cv1 = v1;
+ float cv2 = v2;
+ float cv3 = v3;
+ float cv4 = v4;
+
+ value.setColorSpace (VColor::cmyk);
+ value.set (cv1, cv2, cv3, cv4);
+
+ return value;
+}
+
+void KarbonAIParserBase::doOutputCurrentPath2(PathOutputType type)
+{
+ ensureLayer();
+
+ if (type != POT_Leave)
+ {
+// pottoa(type);
+
+ m_curKarbonPath->setStroke(m_emptyStroke);
+ m_curKarbonPath->setFill(m_emptyFill);
+
+ if ((type != POT_Filled) && (type != POT_Stroked) && (type != POT_FilledStroked)) return;
+ if ((type == POT_Filled) || (type == POT_FilledStroked))
+ {
+/* VFill fill;
+ fill.setColor (toKarbonColor (m_fillColor));
+ m_curKarbonPath->setFill(fill); */
+// qDebug ("set filled");
+ m_curKarbonPath->setFill(m_fill);
+ }
+
+ if ((type == POT_Stroked) || (type == POT_FilledStroked))
+ {
+/* VStroke stroke;
+ stroke.setColor (toKarbonColor (m_strokeColor));
+ m_curKarbonPath->setStroke (stroke); */
+// qDebug ("set stroked");
+ m_curKarbonPath->setStroke (m_stroke);
+ }
+ }
+
+ if (m_ptt == PTT_Combine)
+ {
+// m_pot |= type;
+ if (m_combination == NULL)
+ m_combination = m_curKarbonPath;
+ else
+ m_combination->combine (*m_curKarbonPath);
+
+ m_curKarbonPath = new VPath( 0L );
+
+ return;
+ }
+
+ ensureLayer();
+
+ if (m_groupStack.isEmpty())
+ {
+ m_layer->append( m_curKarbonPath );
+ }
+ else
+ {
+ m_groupStack.top()->append( m_curKarbonPath );
+ }
+
+ m_curKarbonPath = new VPath( 0L );
+}
+
+bool KarbonAIParserBase::parse (QIODevice& fin, QDomDocument &doc)
+{
+
+ bool res = AIParserBase::parse (fin);
+
+// qDebug ("document is %s",doc.toString().latin1());
+ if (res)
+ {
+ qDebug ("before save document");
+ doc = m_document->saveXML();
+ // add paper info, we always need custom for svg (Rob)
+ QDomElement paper = doc.createElement( "PAPER" );
+ doc.documentElement().appendChild( paper );
+ paper.setAttribute( "format", PG_CUSTOM );
+ paper.setAttribute( "width", m_document->width() );
+ paper.setAttribute( "height", m_document->height() );
+
+ qDebug ("after save document");
+ }
+ else
+ {
+ QDomDocument tempDoc;
+ doc = tempDoc;
+ }
+
+ return res;
+}
+
+void KarbonAIParserBase::ensureLayer ()
+{
+ if (!m_layer)
+ {
+ m_layer = new VLayer( 0 );
+ m_document->insertLayer (m_layer);
+ }
+}
+
+
+void KarbonAIParserBase::setupHandlers()
+{
+// qDebug("setupHandler called");
+ m_gstateHandler = new KarbonGStateHandler(this);
+ m_structureHandler = new KarbonStructureHandler(this);
+ m_pathHandler = new KarbonPathHandler(this);
+ m_documentHandler = new KarbonDocumentHandler(this);
+
+ m_textHandler = new TextHandlerBase();
+
+}
+
+void KarbonAIParserBase::teardownHandlers()
+{
+// qDebug("teardownHandler called");
+ delete m_textHandler;
+
+ delete m_gstateHandler;
+ delete m_structureHandler;
+ delete m_pathHandler;
+ delete m_documentHandler;
+}
+
+
+void KarbonDocumentHandler::gotBoundingBox (int llx, int lly, int urx, int ury)
+{
+ delegate->gotBoundingBox(llx,lly,urx,ury);
+}
+
+void KarbonDocumentHandler::gotCreationDate (const char */*val1*/,const char */*val2*/)
+{
+// qDebug ("got creation date [%s], [%s]",val1,val2);
+}
+
+void KarbonDocumentHandler::gotProcessColors (int /*colors*/)
+{
+/* if (colors && PC_Cyan) qDebug ("contains cyan");
+ if (colors && PC_Magenta) qDebug ("contains magenta");
+ if (colors && PC_Yellow) qDebug ("contains yellow");
+ if (colors && PC_Black) qDebug ("contains black"); */
+}
+
+
+void KarbonGStateHandler::gotFillColor (AIColor &color)
+{
+ delegate->gotFillColor (color);
+}
+
+void KarbonGStateHandler::gotStrokeColor (AIColor &color)
+{
+ delegate->gotStrokeColor(color);
+}
+
+void KarbonGStateHandler::gotFlatness (double val)
+{
+ delegate->gotFlatness(val);
+}
+
+void KarbonGStateHandler::gotLineWidth (double val)
+{
+ delegate->gotLineWidth(val);
+}
+
+void KarbonGStateHandler::gotLineCaps (int val)
+{
+ delegate->gotLineCaps(val);
+}
+
+void KarbonGStateHandler::gotLineJoin (int val)
+{
+ delegate->gotLineJoin(val);
+}
+
+void KarbonGStateHandler::gotMiterLimit (double val)
+{
+ delegate->gotMiterLimit(val);
+}
+
+void KarbonGStateHandler::gotWindingOrder (int val)
+{
+ delegate->gotWindingOrder(val);
+}
+
+void KarbonStructureHandler::gotBeginGroup (bool clipping)
+{
+ delegate->gotBeginGroup(clipping);
+}
+
+void KarbonStructureHandler::gotEndGroup (bool clipping)
+{
+ delegate->gotEndGroup(clipping);
+}
+
+void KarbonStructureHandler::gotBeginCombination ()
+{
+ delegate->gotBeginCombination();
+}
+
+void KarbonStructureHandler::gotEndCombination ()
+{
+ delegate->gotEndCombination();
+}
+
+void KarbonPathHandler::gotPathElement (PathElement &element)
+{
+ delegate->gotPathElement (element);
+}
+
+void KarbonPathHandler::gotFillPath (bool closed, bool reset)
+{
+ delegate->gotFillPath(closed, reset, m_fm);
+}
+
+void KarbonPathHandler::gotFillMode (FillMode fm)
+{
+ m_fm = fm;
+}
+
+void KarbonPathHandler::gotStrokePath (bool closed)
+{
+ delegate->gotStrokePath(closed);
+}
+
+void KarbonPathHandler::gotIgnorePath (bool closed, bool reset)
+{
+ delegate->gotIgnorePath(closed, reset);
+}
+
+void KarbonPathHandler::gotClipPath (bool closed)
+{
+ delegate->gotClipPath(closed);
+}
+
+const void pottoa (PathOutputType &data)
+{
+ switch (data)
+ {
+ case POT_Filled : qDebug ("filled"); break;
+ case POT_Stroked : qDebug ("stroked"); break;
+ case POT_FilledStroked : qDebug ("filled/stroked"); break;
+ case POT_Clip : qDebug ("clip"); break;
+ case POT_Ignore : qDebug ("ignore"); break;
+ case POT_Leave : qDebug ("leave"); break;
+ default : qDebug ("unknown");
+ }
+}
+
diff --git a/filters/karbon/ai/karbonaiparserbase.h b/filters/karbon/ai/karbonaiparserbase.h
new file mode 100644
index 00000000..4b6f05a9
--- /dev/null
+++ b/filters/karbon/ai/karbonaiparserbase.h
@@ -0,0 +1,202 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KARBONAIPARSERBASE_H
+#define KARBONAIPARSERBASE_H
+
+#include <aiparserbase.h>
+#include <qptrlist.h>
+#include <qstring.h>
+#include <qpair.h>
+
+#include "aicolor.h"
+
+#include <KoPoint.h>
+#include <core/vcomposite.h>
+#include <core/vdocument.h>
+#include <core/vlayer.h>
+#include <core/vgroup.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <qdom.h>
+
+#include <qptrstack.h>
+
+/**
+ *@author
+ */
+typedef QPair<QString,QString> Parameter;
+typedef QPtrList<Parameter> Parameters;
+typedef QPtrList<PathElement> PathElements;
+
+typedef enum { POT_Filled = 1, POT_Stroked = 2, POT_FilledStroked = 3, POT_Clip = 4, POT_Ignore = 8, POT_Leave = -1, POT_Other = 0 } PathOutputType;
+typedef enum { PTT_Output = 1, PTT_Combine = 2 } PathTransferType;
+
+// typedef struct { int llx, lly, urx, ury; } BoundingBox;
+
+class KarbonAIParserBase;
+class KarbonGStateHandler;
+class KarbonStructureHandler;
+class KarbonPathHandler;
+class KarbonDocumentHandler;
+
+class KarbonDocumentHandler : public DocumentHandlerBase
+{
+ private:
+ KarbonAIParserBase *delegate;
+ public:
+ KarbonDocumentHandler (KarbonAIParserBase *delegate) : DocumentHandlerBase () { this->delegate = delegate; }
+
+ void gotBoundingBox (int llx, int lly, int urx, int ury);
+ void gotCreationDate (const char *val1,const char *val2);
+ void gotProcessColors (int colors);
+};
+
+class KarbonGStateHandler : public GStateHandlerBase
+{
+ private:
+ KarbonAIParserBase *delegate;
+ public:
+ KarbonGStateHandler (KarbonAIParserBase *delegate) : GStateHandlerBase() { this->delegate = delegate; }
+
+ void gotFillColor (AIColor &color);
+ void gotStrokeColor (AIColor &color);
+
+ void gotFlatness (double val);
+ void gotLineWidth (double val);
+ void gotLineCaps (int val);
+ void gotLineJoin (int val);
+ void gotMiterLimit (double val);
+ void gotWindingOrder (int val);
+
+};
+
+class KarbonStructureHandler : public StructureHandlerBase
+{
+ private:
+ KarbonAIParserBase *delegate;
+ public:
+ KarbonStructureHandler (KarbonAIParserBase *delegate) : StructureHandlerBase() { this->delegate = delegate; }
+
+ void gotBeginGroup (bool clipping);
+ void gotEndGroup (bool clipping);
+ void gotBeginCombination ();
+ void gotEndCombination ();
+
+};
+
+class KarbonPathHandler : public PathHandlerBase
+{
+ private:
+ KarbonAIParserBase *delegate;
+ FillMode m_fm;
+ public:
+ KarbonPathHandler (KarbonAIParserBase *delegate) : PathHandlerBase ()
+ {
+ m_fm = FM_EvenOdd;
+ this->delegate = delegate;
+ }
+
+ void gotPathElement (PathElement &element);
+ void gotFillPath (bool closed, bool reset);
+ void gotStrokePath (bool closed);
+ void gotIgnorePath (bool closed, bool reset);
+ void gotClipPath (bool closed);
+ void gotFillMode (FillMode fm);
+
+};
+
+class KarbonAIParserBase : public AIParserBase {
+ friend class KarbonDocumentHandler;
+ friend class KarbonGStateHandler;
+ friend class KarbonStructureHandler;
+ friend class KarbonPathHandler;
+
+public:
+ KarbonAIParserBase();
+ ~KarbonAIParserBase();
+
+ bool parse (QIODevice& fin, QDomDocument &doc);
+private:
+ VPath *m_curKarbonPath;
+ VDocument *m_document;
+ VLayer *m_layer;
+ VPath *m_combination;
+ QPtrStack<VGroup> m_groupStack;
+
+ FillMode m_fm;
+ PathOutputType m_pot;
+ PathTransferType m_ptt;
+
+// BoundingBox m_bbox;
+ KoRect m_bbox;
+ VFill m_fill;
+ VStroke m_stroke;
+/** AIColor m_strokeColor;
+ AIColor m_fillColor;
+ double m_lineWidth;
+ double m_flatness;
+ int m_lineCaps;
+ int m_lineJoin;
+ double m_miterLimit; */
+ int m_windingOrder;
+
+ void doOutputCurrentPath2(PathOutputType type);
+ const VColor toKarbonColor (const AIColor &color);
+ void ensureLayer ();
+
+ VFill m_emptyFill;
+ VStroke m_emptyStroke;
+
+protected:
+ void setupHandlers();
+ void teardownHandlers();
+
+ void parsingStarted();
+ void parsingFinished();
+
+ QString getParamList(Parameters& params);
+
+ void gotPathElement (PathElement &element);
+ void gotFillPath (bool closed, bool reset, FillMode fm = FM_NonZero);
+ void gotStrokePath (bool closed);
+ void gotIgnorePath (bool closed, bool reset);
+ void gotClipPath (bool closed);
+
+ void gotFillColor (AIColor &color);
+ void gotStrokeColor (AIColor &color);
+ void gotBoundingBox (int llx, int lly, int urx, int ury);
+
+ void gotFlatness (double val);
+ void gotLineWidth (double val);
+ void gotLineCaps (int val);
+ void gotLineJoin (int val);
+ void gotMiterLimit (double val);
+ void gotWindingOrder (int val);
+ void gotBeginGroup (bool clipping);
+ void gotEndGroup (bool clipping);
+ void gotBeginCombination ();
+ void gotEndCombination ();
+
+ virtual void gotStartTag (const char *tagName, Parameters& params);
+ virtual void gotEndTag (const char *tagName);
+ virtual void gotSimpleTag (const char *tagName, Parameters& params);
+};
+
+#endif
diff --git a/filters/karbon/applixgraphics/Makefile.am b/filters/karbon/applixgraphics/Makefile.am
new file mode 100644
index 00000000..b3c03f38
--- /dev/null
+++ b/filters/karbon/applixgraphics/Makefile.am
@@ -0,0 +1,20 @@
+####### General stuff
+
+INCLUDES= -I$(srcdir) $(KOFFICE_INCLUDES) $(all_includes)
+libapplixgraphicimport_la_LDFLAGS = -module -avoid-version -no-undefined $(all_libraries)
+
+####### Files
+
+kde_module_LTLIBRARIES = libapplixgraphicimport.la
+
+libapplixgraphicimport_la_SOURCES = applixgraphicimport.cc
+libapplixgraphicimport_la_LIBADD = $(KOFFICE_LIBS)
+noinst_HEADERS = applixgraphicimport.h
+
+METASOURCES = AUTO
+
+service_DATA = kontour_applixgraphic_import.desktop
+servicedir = $(kde_servicesdir)
+
+messages: rc.cpp
+ $(XGETTEXT) *.cc *.cpp -o $(podir)/kontourapplixgraphicsfilter.pot
diff --git a/filters/karbon/applixgraphics/applixgraphicimport.cc b/filters/karbon/applixgraphics/applixgraphicimport.cc
new file mode 100644
index 00000000..2ee52685
--- /dev/null
+++ b/filters/karbon/applixgraphics/applixgraphicimport.cc
@@ -0,0 +1,832 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Enno Bartels <ebartels@nwn.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#define FAKTOR 39.4 // 1000 dots/inch / 2.54 cm/inch = 394 dots/cm = 39.4 dots/mm
+
+#include <config.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <kdebug.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qmessagebox.h>
+#include <KoFilterChain.h>
+#include <kgenericfactory.h>
+#include <math.h>
+
+#include <applixgraphicimport.h>
+
+typedef KGenericFactory<APPLIXGRAPHICImport, KoFilter> APPLIXGRAPHICImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libapplixgraphicimport, APPLIXGRAPHICImportFactory( "kofficefilters" ) )
+
+int s_area = 30517;
+
+/******************************************************************************
+ * class: applixGraphicsLine function: constructor *
+ ******************************************************************************
+ * *
+ * Short description : - Initialize all variables *
+ * *
+ * *
+ ******************************************************************************/
+applixGraphicsLine::applixGraphicsLine()
+{
+ offX = 0;
+ offY = 0;
+ reColor = 0;
+ thickNess = 1; // ??
+
+ for (int i=0; i<5; i++)
+ {
+ ptX[0] = 0;
+ ptY[0] = 0;
+ }
+}
+
+
+
+
+
+/******************************************************************************
+ * class: applixGraphicsRect function: constructor *
+ ******************************************************************************
+ * *
+ * Short description : - Initialize all variables *
+ * *
+ * *
+ ******************************************************************************/
+applixGraphicsRect::applixGraphicsRect() : applixGraphicsLine()
+{
+ for (int i=0; i<7;i++)
+ {
+ bf[i] = 0;
+ lf[i] = 0;
+ }
+
+ for (int i=0; i<5;i++)
+ {
+ sh[i] = 0;
+ }
+
+ for (int i=0; i<8;i++)
+ {
+ pa[i] = 0;
+ }
+
+ for (int i=0; i<3;i++)
+ {
+ vs[i] = 0;
+ }
+
+ for (int i=0; i<2;i++)
+ {
+ xr[i] = 0;
+ }
+
+}
+
+
+
+
+
+/******************************************************************************
+ * class: APPLIXGRAPHICImport function: constructor *
+ ******************************************************************************
+ * *
+ * Short description : constructor *
+ * *
+ * *
+ ******************************************************************************/
+APPLIXGRAPHICImport::APPLIXGRAPHICImport (KoFilter *, const char *, const QStringList&) :
+ KoFilter ()
+{
+
+}
+
+
+
+/******************************************************************************
+ * class: APPLIXGRAPHICImport function: filter *
+ ******************************************************************************
+ * *
+ * Short description : - Read inputfile, *
+ * - convert it to kontour fileformat and *
+ * - save it *
+ * *
+ * *
+ ******************************************************************************/
+KoFilter::ConversionStatus APPLIXGRAPHICImport::convert( const QCString& from, const QCString& to )
+{
+
+ // Check MIME Types
+ if (to!="application/x-karbon" || from!="application/x-applixgraphic")
+ return KoFilter::NotImplemented;
+
+ // Open Inputfile
+ QFile in (m_chain->inputFile());
+ if (!in.open (IO_ReadOnly) )
+ {
+ kdError(30502) << "Unable to open input file!" << endl;
+ in.close ();
+ return KoFilter::FileNotFound;
+ }
+
+ QString str;
+
+ // Create karbon header
+ str += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ str += "<!DOCTYPE karbon>\n";
+ str += " <karbon mime=\"application/x-karbon\" version=\"2\" editor=\"APPLIXGRAPHICS import filter\">\n";
+// str += " <head>\n";
+// str += " <layout width=\"210\" lmargin=\"0\" format=\"a4\" bmargin=\"0\" height=\"297\" rmargin=\"0\" tmargin=\"0\" orientation=\"portrait\"/>\n";
+// str += " <grid dx=\"20\" dy=\"20\" align=\"0\">\n";
+// str += " <helplines align=\"0\"/>\n";
+// str += " </grid>\n";
+// str += " </head>\n";
+ str += " <layer name=\"ag-layer\" visible=\"1\">\n";
+
+ QTextStream stream(&in);
+ int step = in.size()/50;
+ int value = 0;
+ int i = 0;
+ int picture_rememberer = 0;
+ int pos = 0;
+ int vers[3] = { 0, 0, 0 };
+ int rueck; // Check scanf inputs
+ QString mystr;
+
+ // Read Headline
+ mystr = stream.readLine ();
+ rueck = sscanf ((const char *) mystr.latin1() ,
+ "*BEGIN GRAPHICS VERSION=%d/%d ENCODING=%dBIT",
+ &vers[0], &vers[1], &vers[2]);
+ kdDebug (s_area) << "Versions info: " << vers[0] << vers[1] << vers[2] << endl;
+
+ // Check the headline
+ if (rueck <= 0)
+ {
+ kdDebug (s_area) << "Header not correkt - May be it is not an applixgraphics file" << endl;
+ kdDebug (s_area) << "Headerline: " << mystr << endl;
+
+ QMessageBox::critical (0L, "Applixgraphics header problem",
+ QString ("The Applixgraphics header is not correct. "
+ "May be it is not an applixgraphics file! <BR>"
+ "This is the header line I did read:<BR><B>%1</B>").arg(mystr.latin1()),
+ "Comma");
+
+ // i18n( "What is the separator used in this file ? First line is \n%1" ).arg(firstLine),
+ return KoFilter::StupidError;
+ }
+
+ while (!stream.atEnd ())
+ {
+ ++i;
+
+ // Read one line
+ mystr = stream.readLine ();
+ kdDebug (s_area) << "<<" << mystr << ">>" << endl;
+
+ if (mystr == "PICTURE") picture_rememberer = 1;
+ else if (mystr == "END PICTURE") picture_rememberer = 0;
+
+
+ // Detect a point at the first place of the ascii_linie
+ else if ((mystr[0] == '.') && (picture_rememberer == 1))
+ {
+ // Delete point at the first place of the ascii_linie
+ mystr.remove (0, 1);
+ kdDebug (s_area) << "StartPoint recognized <" << mystr << ">" << endl;
+
+
+ /********************************************************************
+ * Element "LINE" *
+ ********************************************************************/
+ if (mystr.startsWith ("LINE AT") )
+ {
+ // Define
+ applixGraphicsLine agLine;
+
+ //str += agLine.read (int, mystr);
+
+ kdDebug (s_area) << " Linie recognized: " << endl;
+ mystr.remove (0, 8);
+ //mystr.remove (0, 7);
+
+
+ //remove_pos = mystr.find ('(');
+ //mystr.remove (0, remove_pos);
+ //agLine.offX= mystr.toInt();
+
+ //remove_pos = mystr.find (',');
+ //mystr.remove (0, remove_pos);
+ //agLine.offY= mystr.toInt();
+ rueck = sscanf ((const char *) mystr.latin1(), "(%d,%d)",
+ &agLine.offX, &agLine.offY);
+ kdDebug (s_area) << " Offset -> x:" << agLine.offX << " y:" << agLine.offY << endl;
+ if (rueck <= 0)
+ {
+ kdDebug (s_area) << "LINE tag not correkt" << endl;
+ kdDebug (s_area) << "LINE: <" << mystr << ">" << endl;
+ return KoFilter::StupidError;
+ }
+
+ do
+ {
+ // Get acutal position
+ pos = in.at ();
+ // Read one line
+ mystr = stream.readLine ();
+
+ if (mystr.startsWith (" RECOLOR ") )
+ {
+ kdDebug (s_area) << " Recolor ";
+ mystr.remove (0, 9);
+ if (mystr == "ON")
+ {
+ kdDebug (s_area) << "On" << endl;
+ agLine.reColor = true;
+ }
+ else if (mystr == "OFF")
+ {
+ kdDebug (s_area) << "Off" << endl;
+ agLine.reColor = false;
+ }
+ else
+ {
+ kdDebug (s_area) << "!!!!! Unknown RECOLOR item <" << mystr << ">" << endl;
+ }
+ }
+ else if (mystr.startsWith (" THICKNESS ") )
+ {
+ kdDebug (s_area) << " Thickness: ";
+ mystr.remove (0, 11);
+ sscanf ((const char *) mystr.latin1(), "%d", &agLine.thickNess);
+ //
+ kdDebug (s_area) << agLine.thickNess << endl;
+ }
+ else if (mystr.startsWith (" PNTS ") )
+ {
+ kdDebug (s_area) << " Pnts : ";
+ mystr.remove (0, 6);
+ sscanf ((const char *) mystr.latin1(), "(%d,%d)(%d,%d)",
+ &agLine.ptX[0], &agLine.ptY[0], &agLine.ptX[1], &agLine.ptY[1]);
+ kdDebug (s_area) << agLine.ptX[0] << " " << agLine.ptY[0] << " " << agLine.ptX[1] << " " << agLine.ptY[1] << endl;
+ }
+
+ }
+ while ((mystr[0] != '.') && (mystr[0] != 'E'));
+
+ // An die Position zurueckspringen
+ in.at (pos);
+
+ // Werte in die Struktur einlagern
+ str += " <polyline arrow1=\"0\" arrow2=\"0\" >\n";
+// str += " <point x=\"" + agLine.ptX[0] + "\" y=\"" + agLine.ptY[0] + "\" />";
+ str += " <point x=\"" ;
+ str += QString::number ((agLine.ptX[0] + agLine.offX)/FAKTOR);
+ str += "\" y=\"";
+ str += QString::number ((agLine.ptY[0] + agLine.offY)/FAKTOR);
+ str += "\" />\n";
+
+// str += " <point x=\"" + agLine.ptX[1] + "\" y=\"" + agLine.ptY[1] + "\" />";
+ str += " <point x=\"";
+ str += QString::number ((agLine.ptX[1] + agLine.offX)/FAKTOR);
+ str += "\" y=\"";
+ str += QString::number ((agLine.ptY[1] + agLine.offY)/FAKTOR);
+ str += "\" />\n";
+ str += " <gobject fillstyle=\"0\" linewidth=\"1\" strokecolor=\"#000000\" strokestyle=\"1\" >\n";
+ str += " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\" />\n";
+ str += " </gobject>\n";
+
+
+
+ str += " </polyline>\n";
+
+
+ }
+ /********************************************************************
+ * Element RPOL Vieleck *
+ ********************************************************************/
+ if (mystr.startsWith ("RPOL AT") )
+ {
+ // Define
+ applixGraphicsLine agLine;
+ int nsides;
+
+ //str += agLine.read (int, mystr);
+
+ kdDebug (s_area) << " RPOL recognized: " << endl;
+ mystr.remove (0, 8);
+
+ rueck = sscanf ((const char *) mystr.latin1(), "(%d,%d)",
+ &agLine.offX, &agLine.offY);
+ kdDebug (s_area) << " Offset -> x:" << agLine.offX << " y:" << agLine.offY << endl;
+ if (rueck <= 0)
+ {
+ kdDebug (s_area) << "RPOL tag not correkt " << endl;
+ kdDebug (s_area) << "RPOL: <" << mystr << ">" << endl;
+ return KoFilter::StupidError;
+ }
+
+ do
+ {
+ // Akutelle Position bestimmen
+ pos = in.at ();
+ // Zeile einlesen
+ mystr = stream.readLine ();
+//checkSubElement (mystr, subelements)
+ if (mystr.startsWith (" RECOLOR ") )
+ {
+ kdDebug (s_area) << " Recolor " ;
+ mystr.remove (0, 9);
+ if (mystr == "ON")
+ {
+ kdDebug (s_area) << "On" << endl;
+ agLine.reColor = true;
+ }
+ else if (mystr == "OFF")
+ {
+ kdDebug (s_area) << "Off" << endl;
+ agLine.reColor = false;
+ }
+ else
+ {
+ kdDebug (s_area) << "!!!!! Whats that <" << mystr << ">" << endl;
+ }
+ }
+ else if (mystr.startsWith (" NSIDES") )
+ {
+ kdDebug (s_area) << " NSIDES: " ;
+ mystr.remove (0, 8);
+ pos = sscanf ((const char *) mystr.latin1(), "%d", &nsides);
+ kdDebug (s_area) << nsides << "(" << pos << ")" << endl;
+ }
+ else if (mystr.startsWith (" PNTS ") )
+ {
+ kdDebug (s_area) << " Pnts : ";
+ mystr.remove (0, 6);
+ sscanf ((const char *) mystr.latin1(), "(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)",
+ &agLine.ptX[0], &agLine.ptY[0], &agLine.ptX[1], &agLine.ptY[1],
+ &agLine.ptX[2], &agLine.ptY[2], &agLine.ptX[3], &agLine.ptY[3],
+ &agLine.ptX[4], &agLine.ptY[4]);
+ kdDebug (s_area) << agLine.ptX[0] << " " << agLine.ptY[0] << " " <<
+ agLine.ptX[1] << " " << agLine.ptY[1] << " " <<
+ agLine.ptX[2] << " " << agLine.ptY[2] << " " <<
+ agLine.ptX[3] << " " << agLine.ptY[3] << " " <<
+ agLine.ptX[4] << " " << agLine.ptY[4] << endl;
+ }
+//checkSubElement() ende
+
+ }
+ while ((mystr[0] != '.') && (mystr[0] != 'E'));
+
+
+
+ // An die Position zurueckspringen
+ in.at (pos);
+
+ int a, b;
+ float wink=0.0;
+ int *x = new int[nsides];
+ int *y = new int[nsides];
+ a = agLine.ptX[2] / 2;
+ b = agLine.ptY[2] / 2;
+ for (int i=0; i<nsides; i++)
+ {
+ x[i] = qRound (a * cos (wink*M_PI/180));
+ y[i] = qRound (b * sin (wink*M_PI/180));
+ wink += (360/nsides);
+ }
+
+ // Werte in die Struktur einlagern
+ str += " <polyline arrow1=\"0\" arrow2=\"0\" >\n";
+ for (int i=0; i<nsides; i++)
+ {
+ str += " <point x=\"" ;
+ str += QString::number ((x[i] + agLine.offX)/FAKTOR);
+ str += "\" y=\"";
+ str += QString::number ((y[i] + agLine.offY)/FAKTOR);
+ str += "\" />\n";
+ }
+
+ str += " <gobject fillstyle=\"0\" linewidth=\"1\" strokecolor=\"#000000\" strokestyle=\"1\" >\n";
+ str += " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\" />\n";
+ str += " </gobject>\n";
+
+
+
+ str += " </polyline>\n";
+
+
+ }
+ /********************************************************************
+ * Element TXT - Text *
+ ********************************************************************/
+ else if (mystr.startsWith ("TXT AT") )
+ {
+ // Define
+ //applixGraphicsText agText;
+ applixGraphicsLine agText;
+
+ kdDebug (s_area) << " Habe Text erkannt (keine Werte uebernommen)" << endl;
+ mystr.remove (0, 7);
+ sscanf ((const char *) mystr.latin1(), "(%d,%d)",
+ &agText.offX, &agText.offY);
+ kdDebug (s_area) << " Offset -> x:" << agText.offX << " y:" << agText.offY << endl;
+
+
+ do
+ {
+ // Aktuelle Position bestimmen
+ pos = in.at ();
+ // Zeile einlesen
+ mystr = stream.readLine ();
+//checkSubElement()
+ if (mystr.startsWith (" RECOLOR ") )
+ {
+ kdDebug (s_area) << " Recolor : ";
+ mystr.remove (0, 9);
+ if (mystr == "ON")
+ {
+ kdDebug (s_area) << "On" << endl;
+ agText.reColor = true;
+ }
+ else if (mystr == "OFF")
+ {
+ kdDebug (s_area) << "Off" << endl;
+ agText.reColor = false;
+ }
+ else
+ {
+ kdDebug (s_area) << "!!!!! Whats that <" << mystr << ">" << endl;
+ }
+ }
+ else if (mystr.startsWith (" .STR") )
+ {
+ kdDebug (s_area) << " Textstring: ";
+
+ // Zeile einlesen
+ agText.str = stream.readLine ();
+ agText.str.remove (0, 3); // delete ront part
+ kdDebug (s_area) << agText.str;
+ }
+ else if (mystr.startsWith (" THICKNESS ") )
+ {
+ kdDebug (s_area) << " Thickness: ";
+ mystr.remove (0, 11);
+ sscanf ((const char *) mystr.latin1(), "%d", &agText.thickNess);
+ kdDebug (s_area) << agText.thickNess << endl;
+ }
+ else if (mystr.startsWith (" PNTS ") )
+ {
+ kdDebug (s_area) << " Pnts : ";
+ mystr.remove (0, 6);
+ sscanf ((const char *) mystr.latin1(), "(%d,%d)(%d,%d)",
+ &agText.ptX[0], &agText.ptY[0], &agText.ptX[1], &agText.ptY[1]);
+ kdDebug (s_area) << agText.ptX[0] << " " << agText.ptY[0] << " " << agText.ptX[1] << " " << agText.ptY[1];
+ }
+//checkSubElement() ende
+
+ }
+ while ((mystr[0] != '.') && (mystr[0] != 'E'));
+
+ // An die Position zurueckspringen
+ in.at (pos);
+
+ // Werte in die Struktur einlagern
+ str += " <text ";
+ str += "x=\"" ;
+ str += QString::number (agText.offX);
+ str += "\" y=\"" ;
+ str += QString::number (agText.offY);
+ str += "\" >\n";
+ str += " <![CDATA[" + agText.str;
+ str += "]]>\n";
+ str += " <gobject fillstyle=\"0\" linewidth=\"1\" strokecolor=\"#000000\" strokestyle=\"1\" >\n";
+ str += " <matrix dx=\"119\" dy=\"310\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\" />\n";
+ str += " </gobject>\n";
+ str += " </text>\n";
+
+ }
+
+ /********************************************************************
+ * Element rectangle *
+ ********************************************************************/
+ else if (mystr.startsWith ("RECT AT"))
+ {
+ applixGraphicsRect agRect;
+
+ kdDebug (s_area) << " Habe Rectangle erkannt " << endl;
+ mystr.remove (0, 8);
+ rueck = sscanf ((const char *)mystr.latin1(), "(%d,%d)", &agRect.offX, &agRect.offY);
+ if (rueck < 1) kdDebug (s_area) <<"Fehler im String <" << mystr.latin1() << ">" << endl;
+ kdDebug (s_area) << " Offset -> x:" << agRect.offX << " y:" << agRect.offY << endl;
+
+
+ do
+ {
+ // Akutelle Position bestimmen
+ pos = in.at ();
+ // read one line
+ mystr = stream.readLine ();
+
+//checkSubElement()
+ // option RECOLOR
+ if (mystr.startsWith (" RECOLOR ") )
+ {
+ kdDebug (s_area) <<(" Recolor : ");
+ mystr.remove (0, 9);
+ if (mystr == "ON")
+ { kdDebug (s_area) << "On" << endl; agRect.reColor = true;}
+ else if (mystr == "OFF")
+ { kdDebug (s_area) << "Off" << endl; agRect.reColor = false;}
+ else
+ {
+ kdDebug (s_area) << "!!!!! Whats that <" << mystr << ">" << endl;
+ }
+ }
+ // option BACKFILL
+ else if (mystr.startsWith (" BACKFILL ") )
+ {
+ kdDebug (s_area) <<(" Backfill: ");
+ mystr.remove (0, 12);
+ sscanf ((const char *)mystr.latin1(), "<%d %d %d %d %d %d %d>",
+ &agRect.bf[0], &agRect.bf[1], &agRect.bf[2],
+ &agRect.bf[3], &agRect.bf[4], &agRect.bf[5],
+ &agRect.bf[6]);
+ kdDebug (s_area) << agRect.bf[0] << " " << agRect.bf[1] << " " <<
+ agRect.bf[2] << " " << agRect.bf[3] << " " <<
+ agRect.bf[4] << " " << agRect.bf[5] << " " <<
+ agRect.bf[6];
+
+ }
+ // option LINEFILL
+ else if (mystr.startsWith (" LINEFILL ") )
+ {
+ kdDebug (s_area) << " Linefill: ";
+ mystr.remove (0, 12);
+ sscanf ((const char *)mystr.latin1(), "<%d %d %d %d %d %d %d>",
+ &agRect.lf[0], &agRect.lf[1], &agRect.lf[2],
+ &agRect.lf[3], &agRect.lf[4], &agRect.lf[5],
+ &agRect.lf[6]);
+ kdDebug (s_area) << agRect.lf[0] << " " << agRect.lf[1] << " " <<
+ agRect.lf[2] << " " << agRect.lf[3] << " " <<
+ agRect.lf[4] << " " << agRect.lf[5] << " " <<
+ agRect.lf[6];
+
+ }
+ // option SHADOW
+ else if (mystr.startsWith (" SHADOW ") )
+ {
+ kdDebug (s_area) << " Shadow : ";
+ mystr.remove (0, 12);
+ sscanf ((const char *)mystr.latin1(), "<%d %d %d %d %d>",
+ &agRect.sh[0], &agRect.sh[1], &agRect.sh[2],
+ &agRect.sh[3], &agRect.sh[4]);
+ kdDebug (s_area) << agRect.sh[0] << " " << agRect.sh[1] << " " <<
+ agRect.sh[2] << " " << agRect.sh[3] << " " <<
+ agRect.sh[4];
+ }
+ // option PARA
+ else if (mystr.startsWith (" PARA ") )
+ {
+ kdDebug (s_area) << " Para : ";
+ mystr.remove (0, 12);
+ sscanf ((const char *)mystr.latin1(), "<%d %d %d %d %d %d %d %d>",
+ &agRect.pa[0], &agRect.pa[1], &agRect.pa[2],
+ &agRect.pa[3], &agRect.pa[4], &agRect.pa[5],
+ &agRect.pa[6], &agRect.pa[7]);
+ kdDebug (s_area) << agRect.pa[0] << " " << agRect.pa[1] << " " <<
+ agRect.pa[2] << " " << agRect.pa[3] << " " <<
+ agRect.pa[4] << " " << agRect.pa[5] << " " <<
+ agRect.pa[6] << " " << agRect.pa[7] ;
+
+ }
+ // option THICKNESS
+ else if (mystr.startsWith (" THICKNESS ") )
+ {
+ kdDebug (s_area) << " Thickness: ";
+ mystr.remove (0, 11);
+ sscanf ((const char *) mystr.latin1(), "%d", &agRect.thickNess);
+ kdDebug (s_area) << agRect.thickNess << endl;
+ }
+ // option V_SPACE
+ else if (mystr.startsWith (" V_SPACE ") )
+ {
+ kdDebug (s_area) << " V_Space : ";
+ mystr.remove (0, 9);
+ sscanf ((const char *)mystr.latin1(), "(%d %d %d)",
+ &agRect.vs[0], &agRect.vs[1], &agRect.vs[2]);
+ kdDebug (s_area) << agRect.vs[0] << " " << agRect.vs[1] << " " << agRect.vs[2];
+ }
+ // option XYRAD
+ else if (mystr.startsWith (" XYRAD ") )
+ {
+ kdDebug (s_area) << " XYRad : ";
+ mystr.remove (0, 7);
+ sscanf ((const char *)mystr.latin1(), "<%d %d>",
+ &agRect.xr[0], &agRect.xr[1]);
+ kdDebug (s_area) << agRect.xr[0] << " " << agRect.xr[1];
+ }
+ // option PNTS
+ else if (mystr.startsWith (" PNTS ") )
+ {
+ kdDebug (s_area) << " Pnts : ";
+ mystr.remove (0, 6);
+ sscanf ((const char *)mystr.latin1(), "(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)",
+ &agRect.ptX[0], &agRect.ptY[0], &agRect.ptX[1], &agRect.ptY[1],
+ &agRect.ptX[2], &agRect.ptY[2], &agRect.ptX[3], &agRect.ptY[3],
+ &agRect.ptX[4], &agRect.ptY[4]);
+ kdDebug (s_area) << agRect.ptX[0] << " " << agRect.ptY[0] << " " <<
+ agRect.ptX[1] << " " << agRect.ptY[1] << " " <<
+ agRect.ptX[2] << " " << agRect.ptY[2] << " " <<
+ agRect.ptX[3] << " " << agRect.ptY[3] << " " <<
+ agRect.ptX[4] << " " << agRect.ptY[4] << endl;
+ }
+
+//checkSubElement() ende
+ }
+ while ((mystr[0] != '.') && (mystr[0] != 'E'));
+
+ // An die Position zurueckspringen
+ in.at (pos);
+
+ // Werte in die Struktur einlagern
+ str += " <rectangle ";
+ str += "x=\"" ;
+ str += QString::number ((agRect.offX)/FAKTOR);
+ str += "\" y=\"";
+ str += QString::number ((agRect.offY)/FAKTOR);
+ str += "\" width=\"" ;
+ str += QString::number ((agRect.ptX[2])/FAKTOR);
+ str += "\" height=\"";
+ str += QString::number ((agRect.ptY[2])/FAKTOR);
+ str += "\" >\n";
+ str += " <polyline arrow1=\"0\" arrow2=\"0\" >\n";
+
+ str += " <point x=\"" ;
+ str += QString::number ((agRect.ptX[0] + agRect.offX)/FAKTOR) ;
+ str += "\" y=\"" ;
+ str += QString::number ((agRect.ptY[0] + agRect.offY)/FAKTOR) ;
+ str += "\" />\n";
+
+ str += " <point x=\"" ;
+ str += QString::number ((agRect.ptX[0] + agRect.ptX[2] + agRect.offX)/FAKTOR) ;
+ str += "\" y=\"" ;
+ str += QString::number ((agRect.ptY[0] + agRect.offY)/FAKTOR) ;
+ str += "\" />\n";
+
+ str += " <point x=\"" ;
+ str += QString::number ((agRect.ptX[0] + agRect.ptX[2] + agRect.offX)/FAKTOR) ;
+ str += "\" y=\"" ;
+ str += QString::number ((agRect.ptY[0] + agRect.ptY[2] + agRect.offY)/FAKTOR) ;
+ str += "\" />\n";
+
+ str += " <point x=\"" ;
+ str += QString::number ((agRect.ptX[0] + agRect.offX)/FAKTOR) ;
+ str += "\" y=\"" ;
+ str += QString::number ((agRect.ptY[0] + agRect.ptY[2] + agRect.offY)/FAKTOR) ;
+ str += "\" />\n";
+
+
+ str += " <gobject fillstyle=\"0\" linewidth=\"1\" strokecolor=\"#000000\" strokestyle=\"1\" >\n";
+ str += " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\" />\n";
+ str += " </gobject>\n";
+ str += " </polyline>\n";
+ str += " </rectangle>\n";
+
+
+
+
+
+
+ }
+ /********************************************************************
+ * Element ELL - Ellipse *
+ ********************************************************************/
+ else if (mystr.startsWith ("ELL AT"))
+ {
+ applixGraphicsRect agEll;
+
+ kdDebug (s_area) << " Habe ELL erkannt (keine Werte uebernommen " << endl;
+ mystr.remove (0, 7);
+ sscanf ((const char *)mystr.latin1(), "(%d,%d)",
+ &agEll.offX, &agEll.offY);
+ kdDebug (s_area) << " Offset -> x:" << agEll.offX << " y:" << agEll.offY << endl;
+
+ do
+ {
+ // Aktuelle Position bestimmen
+ pos = in.at ();
+ // read one line
+ mystr = stream.readLine ();
+
+//checkSubElement()
+ // option RECOLOR
+ if (mystr.startsWith (" RECOLOR ") )
+ {
+ kdDebug (s_area) << " Recolor: ";
+ mystr.remove (0, 9);
+ if (mystr == "ON")
+ {
+ kdDebug (s_area) << "On" << endl;
+ agEll.reColor = true;
+ }
+ else if (mystr == "OFF")
+ {
+ kdDebug (s_area) << "Off" << endl;
+ agEll.reColor = false;
+ }
+ else
+ {
+ kdDebug (s_area) << "!!!!! Whats that <" << mystr << ">" << endl;
+ }
+ }
+ else if (mystr.startsWith (" PNTS ") )
+ {
+ kdDebug (s_area) <<(" Pnts : ");
+ mystr.remove (0, 6);
+ //
+ sscanf ((const char *)mystr.latin1(), "(%d,%d)(%d,%d)(%d,%d)(%d,%d)(%d,%d)",
+ &agEll.ptX[0], &agEll.ptY[0], &agEll.ptX[1], &agEll.ptY[1],
+ &agEll.ptX[2], &agEll.ptY[2], &agEll.ptX[3], &agEll.ptY[3],
+ &agEll.ptX[4], &agEll.ptY[4]);
+ kdDebug (s_area) << agEll.ptX[0] << " " << agEll.ptY[0] << " " <<
+ agEll.ptX[1] << " " << agEll.ptY[1] << " " <<
+ agEll.ptX[2] << " " << agEll.ptY[2] << " " <<
+ agEll.ptX[3] << " " << agEll.ptY[3] << " " <<
+ agEll.ptX[4] << " " << agEll.ptY[4] << endl;
+
+ }
+//checkSubElement() ende
+ }
+ while ((mystr[0] != '.') && (mystr[0] != 'E'));
+
+ // An die Position zurueckspringen
+ in.at (pos);
+
+ // Werte in die Struktur einlagern
+ // ???
+
+ }
+ else
+ {
+ kdDebug (s_area) << "Unbekannt : " << mystr << endl;
+ }
+
+ }
+
+
+ if (i>step)
+ {
+ i=0;
+ value+=2;
+ emit sigProgress (value);
+ }
+ }
+ emit sigProgress(100);
+
+ str += " </layer>\n";
+ str += " </karbon>\n";
+// str += "</DOC>\n";
+
+ kdDebug (s_area) << "Text " << str.utf8() << endl;
+
+ KoStoreDevice* out= m_chain->storageFile( "root", KoStore::Write );
+ if (!out)
+ {
+ kdError(s_area) << "Unable to open output file!" << endl;
+ in.close ();
+ return KoFilter::StorageCreationError;
+ }
+
+ QCString cstring = str.utf8();
+ out->writeBlock ( (const char*)cstring, cstring.size() - 1 );
+
+ in.close ();
+ return KoFilter::OK;
+}
+
+#include <applixgraphicimport.moc>
+
+
+
+
diff --git a/filters/karbon/applixgraphics/applixgraphicimport.h b/filters/karbon/applixgraphics/applixgraphicimport.h
new file mode 100644
index 00000000..a65e26db
--- /dev/null
+++ b/filters/karbon/applixgraphics/applixgraphicimport.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Enno Bartels <ebartels@nwn.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef APPLIXGRAPHICIMPORT_H
+#define APPLIXGRAPHICIMPORT_H
+
+#include <KoFilter.h>
+
+
+class APPLIXGRAPHICImport : public KoFilter {
+
+ Q_OBJECT
+
+public:
+ APPLIXGRAPHICImport (KoFilter *parent, const char *name, const QStringList&);
+ virtual ~APPLIXGRAPHICImport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+};
+
+
+
+
+// Kleinstes Objekt
+class applixGraphicsLine
+{
+ public:
+ int offX;
+ int offY;
+ int reColor;
+ int thickNess;
+ int ptX[5];
+ int ptY[5];
+ QString str;
+
+ applixGraphicsLine (); // Constructor
+};
+
+class applixGraphicsRect : public applixGraphicsLine
+{
+ public:
+ int bf[7];
+ int lf[7];
+
+ int sh[6];
+
+ int pa[8];
+ int vs[3];
+
+ int xr[2]; //XYRAD
+
+ applixGraphicsRect (); // Constructor
+};
+
+#endif // APPLIXGRAPHICIMPORT_H
diff --git a/filters/karbon/applixgraphics/kontour_applixgraphic_import.desktop b/filters/karbon/applixgraphics/kontour_applixgraphic_import.desktop
new file mode 100644
index 00000000..e7d51294
--- /dev/null
+++ b/filters/karbon/applixgraphics/kontour_applixgraphic_import.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Type=Service
+Name=Kontour Applixgraphics Import Filter
+Name[af]=Kontoer Applixgrafika In voer Filter
+Name[ar]=مِرْشَح استيراد Applixgraphics لدى Kontour
+Name[az]=Kontour Applixgraphics Alma Süzgəci
+Name[bg]=Филтър за импортиране от Applixgraphics в Kontour
+Name[br]=Sil enporzh Applixgraphics evit Kontour
+Name[ca]=Filtre d'importació Applixgraphics per a Kontour
+Name[cs]=Importní filtr Applixgraphics pro Kontour
+Name[cy]=Hidlen Fewnforio Applixgraphics Kontour
+Name[da]=Kontour Applixgraphics-importfilter
+Name[de]=Kontour Applixgraphics-Importfilter
+Name[el]=Φίλτρο εισαγωγής Applixgraphics του Kontour
+Name[eo]=Apliks-grafiko-importfiltrilo por Kontour
+Name[es]=Filtro de importación Applixgraphics de Kontour
+Name[et]=Kontouri Applixgraphics'i impordifilter
+Name[eu]=Kontour Applixgraphics-en inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Kontour Applixgraphics
+Name[fi]=Kontour Applixgraphics -tuontisuodin
+Name[fr]=Filtre d'importation Applix Graphics vers Kontour
+Name[fy]=Kontour Applixgrafysk-Ymportfilter
+Name[ga]=Scagaire Iompórtála Kontour
+Name[gl]=Filtro de Importación de Applixgraphics para Kontour
+Name[he]=מסנן ייבוא מ־Applixgraphics ל־Kontour
+Name[hi]=कन्टूर एप्लिक्सग्राफ़िक्स आयात फ़िल्टर
+Name[hr]=Kontour Aplixgraphics filtar uvoza
+Name[hu]=Kontour Applix Graphics importszűrő
+Name[is]=Kontour Applixgraphics innflutningssía
+Name[it]=Filtro di importazione Applixgraphics per Kontour
+Name[ja]=Kontour Applixgraphics インポートフィルタ
+Name[km]=តម្រង​នាំចូល Applixgraphics សម្រាប់ Kontour
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ Applixgraphics ຂອງການແຕ້ມຮູບ K
+Name[lt]=Kontour Applixgraphics importo filtras
+Name[lv]=Kontour Applixgraphics importa filtrs
+Name[ms]=Penapis Import Kontour Applixgraphics
+Name[mt]=Filtru għall-importazzjoni ta' Applixgraphics ġo Kontour
+Name[nb]=Applixgraphics-importfilter for Kontour
+Name[nds]=Applixgraphics-Importfilter för Kontour
+Name[ne]=रूपरेखा एप्लिक्सग्राफिक्स आयात फिल्टर
+Name[nl]=Kontour Applixgraphics-importfilter
+Name[nn]=Applixgraphics-importfilter for Kontour
+Name[pl]=Filtr importu formatu Applixgraphics do Kontour
+Name[pt]=Filtro de Importação de Applixgraphics para o Kontour
+Name[pt_BR]=Filtro de importação de aplicativos gráficos para o Kontour
+Name[ro]=Filtru importare Kontour pentru Applixgraphics
+Name[ru]=Фильтр импорта файлов Applixgraphics в Kontour
+Name[se]=Kontour:a Applixgraphics-sisafievrridansilli
+Name[sk]=Applixgraphics filter pre import pre Kontour
+Name[sl]=Uvozni filter Applixgraphics za Kontour
+Name[sr]=Kontour-ов филтер за увоз из Applixgraphics-а
+Name[sr@Latn]=Kontour-ov filter za uvoz iz Applixgraphics-a
+Name[sv]=Kontour Applixgrafik-importfilter
+Name[ta]=Kontour Applixgraphics இறக்குமதி வடிகட்டி
+Name[tg]=Филтри Воридоти Applixgraphics
+Name[th]=ตัวกรองการนำเข้า Applixgraphics ของวาดภาพ K
+Name[tr]=Kontour Applixgraphics Alma Süzgeci
+Name[uk]=Фільтр імпорту Applixgraphics для Kontour
+Name[uz]=Kontour Applixgraphics import filteri
+Name[uz@cyrillic]=Kontour Applixgraphics импорт филтери
+Name[ven]=Filithra yau dzhenisa ya Kontour Applixgraphics
+Name[xh]=Isihluzi sokurhweba se Kontour Applixgraphics
+Name[zh_CN]=Kontour Applixgraphics 图形导入过滤器
+Name[zh_TW]=Kontour Applix 圖形匯入過濾程式
+X-KDE-Export=application/x-kontour
+X-KDE-Import=application/x-applixgraphics
+X-KDE-Weight=1
+X-KDE-Library=libapplixgraphicimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/applixgraphics/status.html b/filters/karbon/applixgraphics/status.html
new file mode 100644
index 00000000..1c4bde9c
--- /dev/null
+++ b/filters/karbon/applixgraphics/status.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>KOffice filters status: ApplixGraphics FILTER</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666">
+<A NAME="START">&nbsp;</A>
+
+<BR>
+<center>
+ <h1>
+ KOffice filters status: &nbsp;&nbsp;<i>ApplixGraphics FILTER</i>
+ </h1>
+</center>
+
+<hr NOSHADE SIZE="2" WIDTH="70%">
+
+<font size="-1"><b>
+ <A HREF="#import">Import</A> |
+ <A HREF="#export">Export</A>
+</b></font>
+
+<BR><BR><BR>
+<center><a NAME="import"></a></center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER="0" CELLSPACING="0" BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER="0" CELLPADDING="2" BGCOLOR="#FFFFFF" WIDTH="100%">
+
+ <tr BGCOLOR="#DDFFDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>
+ Import ApplixGraphics for karbon<BR>
+ <BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP" WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>11 feb 2001</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">Features</font></b></td>
+ <td>- Can import simple ApplixGraphics documents</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Todo</font></b></td>
+ <td>- Get format and style information and add this into kontour</td>
+ </tr>
+
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">History</font></b></td>
+ <td>
+
+ <table border="0" cellspacing="0">
+ <tr valign="top">
+ <td align="right">27</td>
+ <td align="right">jan</td>
+ <td align="right">2003</td>
+ <td>&nbsp;:&nbsp;&nbsp;</td>
+ <td>Changed the intern settings of this filter from kontour to karbon<br>
+ Moved print function to kdDebug (area=30517) functions <br>
+ </td>
+ </tr>
+ <tr valign="top">
+ <td align="right">11</td>
+ <td align="right">feb</td>
+ <td align="right">2001</td>
+ <td>&nbsp;:&nbsp;&nbsp;</td>
+ <td>Written a filter that only can filter simple applixgraphics files
+ </td>
+ </tr>
+ </table >
+
+ </td>
+ </tr>
+
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Authors&nbsp;</font></b></td>
+ <td><A HREF="mailto:ebartels@nwn.de">Enno Bartels</A></td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">Links</font></b></td>
+ <td><A HREF="http://home.nordwest.net/ebartels/linux/applixinfo/ag/index.html">Fileformat discription</A></td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Progress report </font></b></td>
+ <td>-</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+<br><br><br>
+
+<hr NOSHADE SIZE="1">
+<br><br><br>
+
+
+<center>
+ <a NAME="export"></a>
+</center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER="0" CELLSPACING="0" BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER="0" CELLPADDING="2" BGCOLOR="#FFFFFF" WIDTH="100%">
+ <tr BGCOLOR="#FFDDDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>Export kontour to ApplixGraphics<BR><BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP" WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">Features</font></b></td>
+ <td>None</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Todo</font></b></td>
+ <td>Everything</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">History</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Authors</font></b></td>
+ <td><a href="mailto:null@kde.org">-</a></td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">Links</font></b></td>
+ <td><a href="http://www.koffice.org">-</a></td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP"><b><font size="+1">Progress report </font></b></td>
+ <td>---</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+</body>
+</html>
diff --git a/filters/karbon/eps/Makefile.am b/filters/karbon/eps/Makefile.am
new file mode 100644
index 00000000..3749dfdc
--- /dev/null
+++ b/filters/karbon/eps/Makefile.am
@@ -0,0 +1,37 @@
+kde_module_LTLIBRARIES = \
+ libkarbonepsexport.la \
+ libkarbonepsimport.la
+
+libkarbonepsexport_la_SOURCES = \
+ epsexport.cc \
+ epsexportdlg.cc
+
+libkarbonepsexport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonepsexport_la_LIBADD = $(LIB_KOFFICEUI) ../../../karbon/libkarboncommon.la
+
+libkarbonepsimport_la_SOURCES = epsimport.cc pscommentlexer.cc
+libkarbonepsimport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonepsimport_la_LIBADD = $(LIB_KOFFICEUI)
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/visitors \
+ $(all_includes)
+
+service_DATA = \
+ karbon_eps_export.desktop \
+ karbon_eps_import.desktop \
+ karbon_ps_import.desktop
+
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ epsexport.h \
+ epsexportdlg.h \
+ epsimport.h \
+ pscommentlexer.h
+
+METASOURCES = AUTO
diff --git a/filters/karbon/eps/epsexport.cc b/filters/karbon/eps/epsexport.cc
new file mode 100644
index 00000000..8ded1772
--- /dev/null
+++ b/filters/karbon/eps/epsexport.cc
@@ -0,0 +1,481 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qapplication.h>
+#include <qcstring.h>
+#include <qdatetime.h> // For creation date/time.
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <KoDocumentInfo.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include "epsexport.h"
+#include "epsexportdlg.h"
+#include "vcolor.h"
+#include "vcomposite.h"
+#include "vdashpattern.h"
+#include "vdocument.h"
+#include "vfill.h"
+#include "vgroup.h"
+#include "vlayer.h"
+#include "vpath.h"
+#include "vsegment.h"
+#include "vselection.h"
+#include "vstroke.h"
+#include "vtext.h"
+#include "vcomputeboundingbox.h"
+
+// Define PostScript level1 operators.
+static char l1_newpath = 'N';
+static char l1_closepath = 'C';
+static char l1_moveto = 'm';
+static char l1_curveto = 'c';
+static char l1_lineto = 'l';
+static char l1_stroke = 's';
+static char l1_fill = 'f';
+//static char l1_eofill = 'e';
+static char l1_setlinewidth = 'w';
+static char l1_setdash = 'd';
+static char l1_setrgbcolor = 'r';
+static char l1_gsave = 'S';
+static char l1_grestore = 'R';
+
+
+class EpsExportFactory : KGenericFactory<EpsExport, KoFilter>
+{
+public:
+ EpsExportFactory( void )
+ : KGenericFactory<EpsExport, KoFilter>( "karbonepsexport" )
+ {}
+
+protected:
+ virtual void setupTranslations( void )
+ {
+ KGlobal::locale()->insertCatalogue( "kofficefilters" );
+ }
+};
+
+
+K_EXPORT_COMPONENT_FACTORY( libkarbonepsexport, EpsExportFactory() )
+
+
+EpsExport::EpsExport( KoFilter*, const char*, const QStringList& )
+ : KoFilter(), m_exportHidden( true )
+{
+}
+
+KoFilter::ConversionStatus
+EpsExport::convert( const QCString& from, const QCString& to )
+{
+ if ( to != "image/x-eps" || from != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+
+ if( !storeIn )
+ return KoFilter::StupidError;
+
+
+ KoFilter::ConversionStatus status = KoFilter::OK;
+
+ // Ask questions about PS level etc.
+ EpsExportDlg* dialog = new EpsExportDlg();
+
+ QApplication::setOverrideCursor( Qt::arrowCursor );
+
+ if( dialog->exec() )
+ {
+ // Which PostScript level to support?
+ m_psLevel = dialog->psLevel() + 1;
+ m_exportHidden = dialog->exportHidden();
+
+ QFile fileOut( m_chain->outputFile() );
+ if( !fileOut.open( IO_WriteOnly ) )
+ {
+ QApplication::restoreOverrideCursor();
+ delete( dialog );
+
+ return KoFilter::StupidError;
+ }
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ m_stream = new QTextStream( &fileOut );
+
+ // Load the document.
+ VDocument doc;
+ doc.load( docNode );
+
+ // Process the document.
+ doc.accept( *this );
+
+ delete m_stream;
+ fileOut.close();
+ }
+ else
+ {
+ // Dialog cancelled.
+ status = KoFilter::UserCancelled;
+ }
+
+ QApplication::restoreOverrideCursor();
+ delete( dialog );
+
+ return status;
+}
+
+void
+EpsExport::visitVDocument( VDocument& document )
+{
+ // calculate the documents bounding box
+ VComputeBoundingBox bbox( ! m_exportHidden );
+ document.accept( bbox );
+ const KoRect &rect = bbox.boundingRect();
+
+ // Print a header.
+ *m_stream <<
+ "%!PS-Adobe-3.0 EPSF-3.0\n"
+ "%%BoundingBox: " <<
+ // Round down.
+ qRound( rect.left() - 0.5 ) << " " <<
+ qRound( rect.top() - 0.5 ) << " " <<
+ // Round up.
+ qRound( rect.right() + 0.5 ) << " " <<
+ qRound( rect.bottom() + 0.5 ) << "\n" <<
+ "%%HiResBoundingBox: " <<
+ rect.left() << " " <<
+ rect.top() << " " <<
+ rect.right() << " " <<
+ rect.bottom() << "\n"
+ "%%Creator: Karbon14 EPS Exportfilter 0.5"
+ << endl;
+
+ // Process document info.
+ KoStoreDevice* storeIn;
+ storeIn = m_chain->storageFile( "documentinfo.xml", KoStore::Read );
+
+ if( storeIn )
+ {
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+
+ KoDocumentInfo docInfo;
+ docInfo.load( domIn );
+
+ KoDocumentInfoAuthor* authorPage =
+ static_cast<KoDocumentInfoAuthor*>( docInfo.page( "author" ) );
+
+ // Get creation date/time = "now".
+ QDateTime now( QDateTime::currentDateTime() );
+
+ *m_stream <<
+ "%%CreationDate: (" << now.toString( Qt::LocalDate ) << ")\n"
+ "%%For: (" << authorPage->fullName() << ") (" << authorPage->company() << ")\n"
+ "%%Title: (" << docInfo.title() << ")"
+ << endl;
+ }
+
+
+ // Print operator definitions.
+ *m_stream <<
+ "\n"
+ "/" << l1_newpath << " {newpath} def\n"
+ "/" << l1_closepath << " {closepath} def\n"
+ "/" << l1_moveto << " {moveto} def\n"
+ "/" << l1_curveto << " {curveto} def\n"
+ "/" << l1_lineto << " {lineto} def\n"
+ "/" << l1_stroke << " {stroke} def\n"
+ "/" << l1_fill << " {fill} def\n"
+ "/" << l1_setlinewidth << " {setlinewidth} def\n"
+ "/" << l1_setdash << " {setdash} def\n"
+ "/" << l1_setrgbcolor << " {setrgbcolor} def\n"
+ "/" << l1_gsave << " {gsave} def\n"
+ "/" << l1_grestore << " {grestore} def\n"
+ << endl;
+
+ // Export layers.
+ VVisitor::visitVDocument( document );
+
+ // Finished.
+ *m_stream <<
+ "%%EOF"
+ << endl;
+}
+
+void
+EpsExport::visitVGroup( VGroup& group )
+{
+ VObjectListIterator itr( group.objects() );
+
+ for( ; itr.current(); ++itr )
+ {
+ // do not export hidden child objects
+ if( ! m_exportHidden && ! isVisible( itr.current() ) )
+ continue;
+ itr.current()->accept( *this );
+ }
+}
+
+void
+EpsExport::visitVLayer( VLayer& layer )
+{
+ // do not export hidden layers
+ if( ! m_exportHidden && ! isVisible( &layer ) )
+ return;
+
+ VObjectListIterator itr( layer.objects() );
+
+ for( ; itr.current(); ++itr )
+ {
+ // do not export hidden objects
+ if( ! m_exportHidden && ! isVisible( itr.current() ) )
+ continue;
+ itr.current()->accept( *this );
+ }
+}
+
+void
+EpsExport::visitVPath( VPath& composite )
+{
+ *m_stream << l1_newpath << "\n";
+
+ VVisitor::visitVPath( composite );
+
+ getFill( *composite.fill() );
+ getStroke( *composite.stroke() );
+
+ *m_stream << endl;
+}
+
+void
+EpsExport::visitVSubpath( VSubpath& path )
+{
+ // Export segments.
+ VSubpathIterator itr( path );
+
+ for( ; itr.current(); ++itr )
+ {
+ VSegment *segment = itr.current();
+ if ( segment->isCurve() ) {
+ *m_stream <<
+ itr.current()->point( 0 ).x() << " " <<
+ itr.current()->point( 0 ).y() << " " <<
+ itr.current()->point( 1 ).x() << " " <<
+ itr.current()->point( 1 ).y() << " " <<
+ itr.current()->knot().x() << " " <<
+ itr.current()->knot().y() << " " <<
+ l1_curveto << "\n";
+ } else if ( segment->isLine() ) {
+ *m_stream <<
+ itr.current()->knot().x() << " " <<
+ itr.current()->knot().y() << " " <<
+ l1_lineto << "\n";
+ } else if ( segment->isBegin() ) {
+ *m_stream <<
+ itr.current()->knot().x() << " " <<
+ itr.current()->knot().y() << " " <<
+ l1_moveto << "\n";
+ }
+ }
+
+ if( path.isClosed() )
+ *m_stream << l1_closepath << "\n";
+}
+
+void
+EpsExport::visitVText( VText& text )
+{
+ // TODO: currently we only export the glyphs if available.
+
+ // Export the glyphs (= VPaths).
+ VPathListIterator itr( text.glyphs() );
+
+ for( ; itr.current(); ++itr )
+ {
+ visit( *itr.current() );
+ }
+}
+
+void
+EpsExport::getStroke( const VStroke& stroke )
+{
+ // Solid stroke.
+ if( stroke.type() == VStroke::solid )
+ {
+ // Dash pattern.
+ *m_stream << "[";
+
+ const QValueList<float>&
+ array( stroke.dashPattern().array() );
+
+ QValueListConstIterator<float> itr = array.begin();
+ for( ; itr != array.end(); ++itr )
+ *m_stream << *itr << " ";
+
+ *m_stream <<
+ "] " << stroke.dashPattern().offset() <<
+ " " << l1_setdash << " ";
+
+ getColor( stroke.color() );
+
+ // "setlinewidth", "stroke".
+ *m_stream <<
+ " " << stroke.lineWidth() <<
+ " " << l1_setlinewidth <<
+ " " << l1_stroke << "\n";
+ }
+ else if( stroke.type() == VStroke::grad )
+ {
+ if( m_psLevel == 3 )
+ {
+
+ }
+ }
+}
+
+void
+EpsExport::getFill( const VFill& fill )
+{
+ // Solid fill.
+ if( fill.type() == VFill::solid )
+ {
+ // "gsave".
+ *m_stream << l1_gsave << " ";
+
+ // "setrgbcolor".
+ getColor( fill.color() );
+
+ // "fill", "grestore".
+ *m_stream << " " << l1_fill << " " << l1_grestore << "\n";
+ }
+ // Gradient.
+ else if( fill.type() == VFill::grad )
+ {
+ if( m_psLevel == 3 )
+ {
+ // "gsave".
+ *m_stream << l1_gsave << " ";
+
+ VGradient grad = fill.gradient();
+ QPtrVector<VColorStop> ramp = grad.colorStops();
+ if( ramp.size() < 2 )
+ {
+ if( ramp.size() == 1 )
+ getColor( ramp[0]->color );
+ }
+ if( ramp.size() > 2 || ramp.size() == 2 && ramp[0]->midPoint != 0.5 )
+ {
+ // Gradient with more than two colors or asymmetrical midpoint.
+ for( uint i = 1;i < ramp.size();i++ )
+ {
+ char name[15];
+ sprintf( name, "Function%d", 2 * i - 1 );
+
+ VColorStop stop1 = *ramp[i - 1];
+ VColorStop stop2 = *ramp[i];
+ VColor mid;
+ mid.set( 0.5 * ( stop1.color[0] + stop2.color[0] ), 0.5 * ( stop1.color[1] + stop2.color[1] ), 0.5 * ( stop1.color[2] + stop2.color[2] ) );
+ *m_stream << "/" << name << " 7 dict def " << name << " begin\n" << "\t/FunctionType 2 def\n"
+ << "\t/Domain [ 0 1 ] def\n" << "\t/C0 [ " << stop1.color[0] << " " << stop1.color[1] << " "
+ << stop1.color[2] << " ] def\n" << "\t/C1 [ " << mid[0] << " " << mid[1] << " "
+ << mid[2] << " ] def\n" << "\t/N 1 def\n" << "end\n";
+
+ sprintf( name, "Function%d", 2 * i );
+
+ *m_stream << "/" << name << " 7 dict def " << name << " begin\n" << "\t/FunctionType 2 def\n" << "\t/Domain [ 0 1 ] def\n"
+ << "\t/C0 [ " << mid[0] << " " << mid[1] << " " << mid[2] << " ] def\n" << "\t/C1 [ " << stop2.color[0] << " "
+ << stop2.color[1] << " " << stop2.color[2] << " ] def\n" << "\t/N 1 def\n" << "end\n";
+ }
+ }
+ if( grad.type() == VGradient::linear )
+ *m_stream << "clip newpath\n" << "/DeviceRGB setcolorspace\n" << "<<\n" << "\t/ShadingType 2\n" << "\t/ColorSpace /DeviceRGB\n" << "\t/Coords [ "
+ << grad.origin().x() << " " << grad.origin().y() << " " << grad.vector().x() << " " << grad.vector().y() << " ]\n\t/Extend[ true true ]\n" << "\t/Function <<\n";
+ else if( grad.type() == VGradient::radial )
+ {
+ double r = sqrt( pow( grad.vector().x() - grad.origin().x(), 2 ) + pow( grad.vector().y() - grad.origin().y(), 2 ) );
+ *m_stream << "clip newpath\n" << "/DeviceRGB setcolorspace\n" << "<<\n" << "\t/ShadingType 3\n" << "\t/ColorSpace /DeviceRGB\n" << "\t/Coords [ "
+ << grad.origin().x() << " " << grad.origin().y() << " 0.0 " << grad.origin().x() << " " << grad.origin().y()
+ << " " << r << "]\n\t\t/Extend [ false true ]\n" << "\t/Function <<\n";
+ }
+ if( ramp.size() == 2 && ramp[0]->midPoint == 0.5 )
+ {
+ // Gradient with only two colors and symmetrical midpoint.
+ VColorStop stop1 = *ramp[0];
+ VColorStop stop2 = *ramp[1];
+ *m_stream << "\t\t/FunctionType 2\n" << "\t\t/C0 [ " << stop1.color[0] << " " << stop1.color[1] << " " << stop1.color[2]
+ << " ]\n" << "\t\t/C1 [ " << stop2.color[0] << " " << stop2.color[1] << " " << stop2.color[2] << " ]\n" << "\t\t/N 1\n";
+ }
+ else if( ramp.size() > 2 || ramp.size() == 2 && ramp[0]->midPoint != 0.5 )
+ {
+ // Gradient with more than two colors or asymmetrical midpoint.
+ *m_stream << "\t\t/FunctionType 3\n" << "\t\t/Functions [ ";
+ for( uint i = 1; i < ( 2 * ramp.size() - 1 );i++ )
+ *m_stream << "Function" << i << " ";
+ *m_stream << "]\n" << "\t\t/Bounds [";
+ for( uint i = 0;i < ramp.size() - 1;i++ )
+ {
+ VColorStop stop = *ramp[i];
+ if( i > 0 )
+ *m_stream << " " << stop.rampPoint;
+ *m_stream << " " << ( stop.rampPoint + ( ramp[i + 1]->rampPoint - stop.rampPoint ) * stop.midPoint );
+ }
+ *m_stream << " ]\n" << "\t\t/Encode [ ";
+ for( uint i = 0;i < 2 * ramp.size() - 2;i++ )
+ *m_stream << "0 1 ";
+ *m_stream << "]\n";
+ }
+ *m_stream << "\t\t/Domain [ " << ramp[0]->rampPoint << " "
+ << ramp[ramp.size() - 1]->rampPoint << " ]\n" << "\t>>\n" << ">>\n";
+ // "shfill", "grestore".
+ *m_stream << " shfill " << l1_grestore << "\n";
+ }
+ }
+}
+
+void
+EpsExport::getColor( const VColor& color )
+{
+ VColor copy( color );
+ copy.setColorSpace( VColor::rgb );
+
+ *m_stream <<
+ copy[0] << " " <<
+ copy[1] << " " <<
+ copy[2] << " " << l1_setrgbcolor;
+}
+
+bool
+EpsExport::isVisible( const VObject* object ) const
+{
+ return object->state() != VObject::hidden && object->state() != VObject::hidden_locked;
+}
+
+#include "epsexport.moc"
diff --git a/filters/karbon/eps/epsexport.h b/filters/karbon/eps/epsexport.h
new file mode 100644
index 00000000..b2dd4919
--- /dev/null
+++ b/filters/karbon/eps/epsexport.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __EPSEXPORT_H__
+#define __EPSEXPORT_H__
+
+
+#include <KoFilter.h>
+
+#include "vvisitor.h"
+
+class QTextStream;
+class VColor;
+class VPath;
+class VDocument;
+class VFill;
+class VGroup;
+class VLayer;
+class VSubpath;
+class VStroke;
+class VText;
+
+
+class EpsExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ EpsExport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~EpsExport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+private:
+ virtual void visitVPath( VPath& composite );
+ virtual void visitVDocument( VDocument& document );
+ virtual void visitVSubpath( VSubpath& path );
+ virtual void visitVText( VText& text );
+ virtual void visitVGroup( VGroup& group );
+ virtual void visitVLayer( VLayer& layer );
+
+ void getStroke( const VStroke& stroke );
+ void getFill( const VFill& fill );
+ void getColor( const VColor& color );
+
+ bool isVisible( const VObject* object ) const;
+
+ QTextStream* m_stream;
+
+ uint m_psLevel;
+ bool m_exportHidden;
+};
+
+#endif
+
diff --git a/filters/karbon/eps/epsexportdlg.cc b/filters/karbon/eps/epsexportdlg.cc
new file mode 100644
index 00000000..2fb34e14
--- /dev/null
+++ b/filters/karbon/eps/epsexportdlg.cc
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qstring.h>
+#include <qvbox.h>
+#include <qcheckbox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "epsexportdlg.h"
+
+
+EpsExportDlg::EpsExportDlg( QWidget* parent, const char* name )
+ : KDialogBase( parent, name, true, i18n( "EPS Export" ), Ok | Cancel )
+{
+ QVBox* page = makeVBoxMainWidget();
+
+ m_psLevelButtons = new QButtonGroup( 1, QGroupBox::Horizontal,
+ i18n( "Options" ), page );
+
+ QRadioButton* radio;
+ radio = new QRadioButton( i18n( "PostScript level 1" ), m_psLevelButtons );
+ radio = new QRadioButton( i18n( "PostScript level 2" ), m_psLevelButtons );
+ radio = new QRadioButton( i18n( "PostScript level 3" ), m_psLevelButtons );
+
+ m_hiddenExport = new QCheckBox( i18n( "Export hidden layers" ), page );
+ m_hiddenExport->setChecked( true );
+
+ m_psLevelButtons->setRadioButtonExclusive( true );
+ m_psLevelButtons->setButton( 2 );
+}
+
+uint
+EpsExportDlg::psLevel() const
+{
+ return static_cast<uint>(
+ m_psLevelButtons->id( m_psLevelButtons->selected() ) );
+}
+
+bool
+EpsExportDlg::exportHidden() const
+{
+ return m_hiddenExport->isChecked();
+}
+#include "epsexportdlg.moc"
+
diff --git a/filters/karbon/eps/epsexportdlg.h b/filters/karbon/eps/epsexportdlg.h
new file mode 100644
index 00000000..332ca882
--- /dev/null
+++ b/filters/karbon/eps/epsexportdlg.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __VEPSEXPORTDLG_H__
+#define __VEPSEXPORTDLG_H__
+
+#include <kdialogbase.h>
+
+
+class QButtonGroup;
+class QCheckBox;
+
+class EpsExportDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ EpsExportDlg( QWidget* parent = 0L, const char* name = 0L );
+
+ uint psLevel() const;
+ bool exportHidden() const;
+private:
+ QButtonGroup* m_psLevelButtons;
+ QCheckBox* m_hiddenExport;
+};
+
+#endif
+
diff --git a/filters/karbon/eps/epsimport.cc b/filters/karbon/eps/epsimport.cc
new file mode 100644
index 00000000..2ff34a94
--- /dev/null
+++ b/filters/karbon/eps/epsimport.cc
@@ -0,0 +1,117 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcstring.h>
+#include <qstring.h>
+#include <qfile.h>
+
+#include <kgenericfactory.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <krun.h>
+#include <kprocess.h>
+
+#include <kdebug.h>
+
+#include "epsimport.h"
+#include "pscommentlexer.h"
+
+class EpsImportFactory : KGenericFactory<EpsImport, KoFilter>
+{
+public:
+ EpsImportFactory( void )
+ : KGenericFactory<EpsImport, KoFilter>( "karbonepsimport" )
+ {}
+
+protected:
+ virtual void setupTranslations( void )
+ {
+ KGlobal::locale()->insertCatalogue( "kofficefilters" );
+ }
+};
+
+K_EXPORT_COMPONENT_FACTORY( libkarbonepsimport, EpsImportFactory() )
+
+EpsImport::EpsImport( KoFilter*, const char*, const QStringList& )
+ : KoFilter()
+{
+}
+
+EpsImport::~EpsImport()
+{
+}
+
+KoFilter::ConversionStatus
+EpsImport::convert( const QCString& from, const QCString& to )
+{
+ if(
+ to != "application/illustrator" ||
+ (
+ from != "image/x-eps" &&
+ from != "application/postscript" ) )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+ // Copy input filename:
+ QString input = m_chain->inputFile();
+
+
+ // EPS original bounding box
+ int llx = -1, lly = -1, urx = -1, ury = -1;
+ BoundingBoxExtractor extractor;
+
+ QFile file (input);
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ extractor.parse (file);
+ llx = extractor.llx();
+ lly = extractor.lly();
+ urx = extractor.urx();
+ ury = extractor.ury();
+ file.close();
+ }
+ else
+ qDebug ("file could not be opened");
+
+ // sed filter
+ QString sedFilter = QString ("sed -e \"s/%%BoundingBox: 0 0 612 792/%%BoundingBox: %1 %2 %3 %4/g\"").
+ arg(llx).arg(lly).arg(urx).arg(ury);
+
+ // Build ghostscript call to convert ps/eps -> ai:
+ QString command(
+ "gs -q -P- -dBATCH -dNOPAUSE -dSAFER -dPARANOIDSAFER -dNODISPLAY ps2ai.ps ");
+ command += KProcess::quote(input);
+ command += " | ";
+ command += sedFilter;
+ command += " > ";
+ command += KProcess::quote(m_chain->outputFile());
+
+ qDebug ("command to execute is (%s)", QFile::encodeName(command).data());
+
+ // Execute it:
+ if( !system( QFile::encodeName(command)) )
+ return KoFilter::OK;
+ else
+ return KoFilter::StupidError;
+}
+
+#include "epsimport.moc"
+
diff --git a/filters/karbon/eps/epsimport.h b/filters/karbon/eps/epsimport.h
new file mode 100644
index 00000000..15673297
--- /dev/null
+++ b/filters/karbon/eps/epsimport.h
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __EPSIMPORT_H__
+#define __EPSIMPORT_H__
+
+#include <qobject.h>
+
+#include <KoFilter.h>
+
+class QDomElement;
+class QTextStream;
+
+class EpsImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ EpsImport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~EpsImport();
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+};
+
+#endif
+
diff --git a/filters/karbon/eps/karbon_eps_export.desktop b/filters/karbon/eps/karbon_eps_export.desktop
new file mode 100644
index 00000000..4ee7d6f3
--- /dev/null
+++ b/filters/karbon/eps/karbon_eps_export.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon14 EPS Export Filter
+Name[af]=Karbon14 Eps Voer uit Filter
+Name[ar]=مِرْشَح تصدير EPS لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в EPS
+Name[br]=Sil ezporzh EPS evit Karbon14
+Name[ca]=Filtre d'exportació EPS per a Karbon14
+Name[cs]=Exportní filtr do formátu EPS pro Karbon14
+Name[cy]=Hidlen Allforio EPS Karbon14
+Name[da]=Karbon14 EPS-eksportfilter
+Name[de]=Karbon14 EPS-Exportfilter
+Name[el]=Φίλτρο εξαγωγής EPS του Karbon14
+Name[eo]=Karbon-EPS-eksportfiltrilo
+Name[es]=Filtro de exportación EPS de Karbon14
+Name[et]=Karbon14 EPS-i ekspordifilter
+Name[eu]=Karbon14-en EPS esportaziorako iragazkia
+Name[fa]=پالایۀ صادرات Karbon14 EPS
+Name[fi]=Karbon14 EPS -vientisuodin
+Name[fr]=Filtre d'exportation EPS de Karbon 14
+Name[fy]=EPS-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála EPS Karbon14
+Name[gl]=Filtro de Exportación de EPS para Karbon14
+Name[he]=מסנן ייצוא מ־Karbon14 ל־EPS
+Name[hr]=Karbon14 EPS filtar izvoza
+Name[hu]=Karbon14 EPS exportszűrő
+Name[is]=Karbon14 EPS útflutningssía
+Name[it]=Filtro di esportazione EPS per Karbon14
+Name[ja]=Karbon14 EPS エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ EPS សម្រាប់ Karbon14
+Name[lo]= ຕົວຕອງການສົ່ງອອກ EPS ຂອງຄາຮ໌ບອນ14
+Name[lt]=Karbon14 EPS eksportavimo filtras
+Name[lv]=Karbon14 EPS eksporta filtrs
+Name[ms]=Penapis Eksport Karbon14 EPS
+Name[mt]=Filtru għall-esportazzjoni ta' EPS minn ġo Karbon14
+Name[nb]=EPS-eksportfiler for Karbon14
+Name[nds]=EPS-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ इपिएस निर्यात फिल्टर
+Name[nl]=EPS-exportfilter voor Karbon14
+Name[nn]=EPS-eksportfilter for Karbon14
+Name[pl]=Filtr eksportu do formatu EPS z Karbon14
+Name[pt]=Filtro de Exportação de EPS para o Karbon14
+Name[pt_BR]=Filtro de Exportação EPS do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru EPS
+Name[ru]=Фильтр экспорта рисунков Karbon14 в EPS
+Name[se]=Karbon14:a EPS-olggosfievrridansilli
+Name[sk]=EPS filter pre export z Karbon14
+Name[sl]=Izvozni filter EPS za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у EPS
+Name[sr@Latn]=Karbon14-ov filter za izvoz u EPS
+Name[sv]=Karbon14 EPS-exportfilter
+Name[ta]=Karbon EPS வடிகட்டி ஏற்றுமதி
+Name[tg]=Karbon14 EPS Филтри Содирот
+Name[th]=ตัวกรองการส่งออก EPS ของคาร์บอน14
+Name[tr]=Karbon14 EPS Aktarma Filtresi
+Name[uk]=Фільтр експорту EPS для Karbon14
+Name[uz]=Karbon14 EPS eksport filteri
+Name[uz@cyrillic]=Karbon14 EPS экспорт филтери
+Name[xh]=Isihluzi Sokurhweba ngaphandle se Karbon14 EPS
+Name[zh_CN]=Karbon14 EPS 导出过滤器
+Name[zh_TW]=Karbon14 EPS 匯出過濾程式
+X-KDE-Export=image/x-eps
+X-KDE-Import=application/x-karbon
+X-KDE-Weight=1
+X-KDE-Library=libkarbonepsexport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/eps/karbon_eps_import.desktop b/filters/karbon/eps/karbon_eps_import.desktop
new file mode 100644
index 00000000..83cae529
--- /dev/null
+++ b/filters/karbon/eps/karbon_eps_import.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon14 EPS Import Filter
+Name[af]=Karbon14 Eps In voer Filter
+Name[ar]=مِرْشَح استيراد EPS لدى Karbon14
+Name[bg]=Филтър за импортиране от EPS в Karbon14
+Name[br]=Sil enporzh EPS evit Karbon14
+Name[ca]=Filtre d'importació EPS per a Karbon14
+Name[cs]=Exportní filtr do formátu EPS pro Karbon14
+Name[cy]=Hidlen Fewnforio EPS Karbon14
+Name[da]=Karbon14 EPS-importfilter
+Name[de]=Karbon14 EPS-Importfilter
+Name[el]=Φίλτρο εισαγωγής EPS του Karbon14
+Name[eo]=Karbon-EPS-importfiltrilo
+Name[es]=Filtro de importación de Karbon14 EPS
+Name[et]=Karbon14 EPS-i impordifilter
+Name[eu]=Karbon14-en EPS inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon14 EPS
+Name[fi]=Karbon14 EPS -tuontisuodin
+Name[fr]=Filtre d'importation EPS de Karbon 14
+Name[fy]=EPS-Ymportfilter foar Karbon14
+Name[ga]=Scagaire Iompórtála EPS Karbon14
+Name[gl]=Filtro de Importación de EPS para Karbon14
+Name[he]=מסנן ייבוא מ־EPS ל־Karbon14
+Name[hr]=Karbon14 EPS filtar uvoza
+Name[hu]=Karbon14 EPS importszűrő
+Name[is]=Karbon14 EPS innflutningssía
+Name[it]=Filtro di importazione EPS per Karbon14
+Name[ja]=Karbon14 EPS インポートフィルタ
+Name[km]=តម្រង​នាំចូល EPS សម្រាប់ Karbon14
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ EPS ຂອງຄາຮ໌ບອນ14
+Name[lt]=Karbon14 EPS importavimo filtras
+Name[lv]=Karbon14 EPS importa filtrs
+Name[ms]=Penapis Import Karbon14 EPS
+Name[mt]=Filtru għall-importazzjoni ta' EPS għal Karbon14
+Name[nb]=EPS-importfilter for Karbon14
+Name[nds]=EPS-Importfilter för Karbon14
+Name[ne]=कार्बन१४ इपिएस आयात फिल्टर
+Name[nl]=EPS-importfilter voor Karbon14
+Name[nn]=EPS-eksportfilter for Karbon14
+Name[pl]=Filtr importu formatu EPS do Karbon14
+Name[pt]=Filtro de Importação de EPS para o Karbon14
+Name[pt_BR]=Filtro de Importação EPS do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru EPS
+Name[ru]=Фильтр импорта EPS в Karbon14
+Name[se]=Karbon14:a EPS-sisafievrridansilli
+Name[sk]=EPS filter pre export z Karbon14
+Name[sl]=Uvozni filter EPS za Karbon14
+Name[sr]=Karbon14-ов филтер за увоз из EPS-а
+Name[sr@Latn]=Karbon14-ov filter za uvoz iz EPS-a
+Name[sv]=Karbon14 EPS-exportfilter
+Name[ta]=Karbon 14 EPS இறக்குமதி வடிகட்டி
+Name[tg]=Karbon14 EPS Филтри Воридот
+Name[th]=ตัวกรองการนำเข้า EPS ของคาร์บอน14
+Name[tr]=Karbon14 EPS Alma Filtresi
+Name[uk]=Фільтр експорту EPS для Karbon14
+Name[uz]=Karbon14 EPS import filteri
+Name[uz@cyrillic]=Karbon14 EPS импорт филтери
+Name[xh]=Isihluzi Sokurhweba se Karbon14 EPS
+Name[zh_CN]=Karbon14 EPS 导入过滤器
+Name[zh_TW]=Karbon14 EPS 匯出過濾程式
+X-KDE-Export=application/illustrator
+X-KDE-Import=image/x-eps
+X-KDE-Weight=1
+X-KDE-Library=libkarbonepsimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/eps/karbon_ps_import.desktop b/filters/karbon/eps/karbon_ps_import.desktop
new file mode 100644
index 00000000..1599fcca
--- /dev/null
+++ b/filters/karbon/eps/karbon_ps_import.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon14 EPS Import Filter
+Name[af]=Karbon14 Eps In voer Filter
+Name[ar]=مِرْشَح استيراد EPS لدى Karbon14
+Name[bg]=Филтър за импортиране от EPS в Karbon14
+Name[br]=Sil enporzh EPS evit Karbon14
+Name[ca]=Filtre d'importació EPS per a Karbon14
+Name[cs]=Exportní filtr do formátu EPS pro Karbon14
+Name[cy]=Hidlen Fewnforio EPS Karbon14
+Name[da]=Karbon14 EPS-importfilter
+Name[de]=Karbon14 EPS-Importfilter
+Name[el]=Φίλτρο εισαγωγής EPS του Karbon14
+Name[eo]=Karbon-EPS-importfiltrilo
+Name[es]=Filtro de importación de Karbon14 EPS
+Name[et]=Karbon14 EPS-i impordifilter
+Name[eu]=Karbon14-en EPS inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon14 EPS
+Name[fi]=Karbon14 EPS -tuontisuodin
+Name[fr]=Filtre d'importation EPS de Karbon 14
+Name[fy]=EPS-Ymportfilter foar Karbon14
+Name[ga]=Scagaire Iompórtála EPS Karbon14
+Name[gl]=Filtro de Importación de EPS para Karbon14
+Name[he]=מסנן ייבוא מ־EPS ל־Karbon14
+Name[hr]=Karbon14 EPS filtar uvoza
+Name[hu]=Karbon14 EPS importszűrő
+Name[is]=Karbon14 EPS innflutningssía
+Name[it]=Filtro di importazione EPS per Karbon14
+Name[ja]=Karbon14 EPS インポートフィルタ
+Name[km]=តម្រង​នាំចូល EPS សម្រាប់ Karbon14
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ EPS ຂອງຄາຮ໌ບອນ14
+Name[lt]=Karbon14 EPS importavimo filtras
+Name[lv]=Karbon14 EPS importa filtrs
+Name[ms]=Penapis Import Karbon14 EPS
+Name[mt]=Filtru għall-importazzjoni ta' EPS għal Karbon14
+Name[nb]=EPS-importfilter for Karbon14
+Name[nds]=EPS-Importfilter för Karbon14
+Name[ne]=कार्बन१४ इपिएस आयात फिल्टर
+Name[nl]=EPS-importfilter voor Karbon14
+Name[nn]=EPS-eksportfilter for Karbon14
+Name[pl]=Filtr importu formatu EPS do Karbon14
+Name[pt]=Filtro de Importação de EPS para o Karbon14
+Name[pt_BR]=Filtro de Importação EPS do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru EPS
+Name[ru]=Фильтр импорта EPS в Karbon14
+Name[se]=Karbon14:a EPS-sisafievrridansilli
+Name[sk]=EPS filter pre export z Karbon14
+Name[sl]=Uvozni filter EPS za Karbon14
+Name[sr]=Karbon14-ов филтер за увоз из EPS-а
+Name[sr@Latn]=Karbon14-ov filter za uvoz iz EPS-a
+Name[sv]=Karbon14 EPS-exportfilter
+Name[ta]=Karbon 14 EPS இறக்குமதி வடிகட்டி
+Name[tg]=Karbon14 EPS Филтри Воридот
+Name[th]=ตัวกรองการนำเข้า EPS ของคาร์บอน14
+Name[tr]=Karbon14 EPS Alma Filtresi
+Name[uk]=Фільтр експорту EPS для Karbon14
+Name[uz]=Karbon14 EPS import filteri
+Name[uz@cyrillic]=Karbon14 EPS импорт филтери
+Name[xh]=Isihluzi Sokurhweba se Karbon14 EPS
+Name[zh_CN]=Karbon14 EPS 导入过滤器
+Name[zh_TW]=Karbon14 EPS 匯出過濾程式
+X-KDE-Export=application/illustrator
+X-KDE-Import=application/postscript
+X-KDE-Weight=1
+X-KDE-Library=libkarbonepsimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/eps/pscommentlexer.cc b/filters/karbon/eps/pscommentlexer.cc
new file mode 100644
index 00000000..46d993dc
--- /dev/null
+++ b/filters/karbon/eps/pscommentlexer.cc
@@ -0,0 +1,324 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <qstringlist.h>
+#include "pscommentlexer.h"
+
+#define CATEGORY_WHITESPACE -1
+#define CATEGORY_ALPHA -2
+#define CATEGORY_DIGIT -3
+#define CATEGORY_SPECIAL -4
+#define CATEGORY_LETTERHEX -5
+#define CATEGORY_INTTOOLONG -6
+
+#define CATEGORY_ANY -127
+
+#define MAX_INTLEN 9
+#define MIN_HEXCHARS 6
+
+#define STOP 0
+
+int iswhitespace(char c){
+ return (c==' ')||(c=='\n')||(c=='\t')||(c=='\r');
+}
+
+int isSpecial(char c){
+ return (c=='*')||(c=='_')||(c=='?')||(c=='~')||(c=='-')||(c=='^')||(c=='`')||(c=='!')||(c=='.')||(c=='@')||(c=='&')||(c=='$')||(c=='=');
+}
+
+int isletterhex(char c){
+ return (c=='A')||(c=='B')||(c=='C')||(c=='D')||(c=='E')||(c=='F');
+}
+
+const char*statetoa (State state){
+ switch (state)
+ {
+ case State_Comment : return "comment";
+ case State_CommentEncodedChar : return "encoded char (comment)";
+ default : return "unknown";
+ }
+}
+
+typedef struct {
+ State oldState;
+ char c;
+ State newState;
+ Action action;
+} Transition;
+
+static Transition transitions[] = {
+ { State_Comment, '\n', State_Start, Action_Output},
+ { State_Comment, '\r', State_Start, Action_Output},
+ { State_Comment, '\\', State_CommentEncodedChar, Action_InitTemp},
+ { State_Comment, CATEGORY_ANY, State_Comment, Action_Copy},
+ { State_CommentEncodedChar, '\\', State_Comment, Action_Copy},
+ { State_CommentEncodedChar, CATEGORY_DIGIT, State_CommentEncodedChar, Action_CopyTemp},
+ { State_CommentEncodedChar, CATEGORY_ANY, State_Comment, Action_DecodeUnget},
+ { State_Start, '%', State_Comment, Action_Ignore},
+ { State_Start, CATEGORY_ANY, State_Start, Action_Ignore},
+ { State_Start, STOP, State_Start, Action_Abort}
+};
+
+PSCommentLexer::PSCommentLexer(){
+}
+PSCommentLexer::~PSCommentLexer(){
+}
+
+bool PSCommentLexer::parse (QIODevice& fin){
+ char c;
+
+ m_buffer.clear();
+ m_curState = State_Start;
+
+ parsingStarted();
+
+ while (!fin.atEnd())
+ {
+ c = fin.getch ();
+
+// qDebug ("got %c", c);
+
+ State newState;
+ Action action;
+
+ nextStep (c, &newState, &action);
+
+ switch (action)
+ {
+ case Action_Copy :
+ m_buffer.append (c);
+ break;
+ case Action_CopyOutput :
+ m_buffer.append (c);
+ doOutput();
+ break;
+ case Action_Output :
+ doOutput();
+ break;
+ case Action_OutputUnget :
+ doOutput();
+ fin.ungetch(c);
+ break;
+ case Action_Ignore :
+ /* ignore */
+ break;
+ case Action_Abort :
+ qWarning ( "state %s / %s char %c (%d)" , statetoa(m_curState), statetoa(newState), c, c );
+ parsingAborted();
+ return false;
+ break;
+ case Action_InitTemp :
+ m_temp.clear();
+ break;
+ case Action_CopyTemp :
+ m_temp.append (c);
+ break;
+ case Action_DecodeUnget :
+ m_buffer.append (decode());
+ fin.ungetch(c);
+ break;
+ default :
+ qWarning ( "unknown action: %d ", action);
+ }
+
+ m_curState = newState;
+ }
+
+ parsingFinished();
+ return true;
+}
+
+void PSCommentLexer::doOutput ()
+{
+ if (m_buffer.length() == 0) return;
+ switch (m_curState)
+ {
+ case State_Comment :
+ gotComment (m_buffer.latin1());
+ break;
+ default:
+ qWarning ( "unknown state: %d", m_curState );
+ }
+
+ m_buffer.clear();
+}
+
+void PSCommentLexer::gotComment (const char *value) {
+ qDebug ( "gotComment: %s ", value );
+}
+
+void PSCommentLexer::parsingStarted() {
+ qDebug ( "parsing started" );
+}
+
+void PSCommentLexer::parsingFinished() {
+ qDebug ( "parsing finished" );
+}
+
+void PSCommentLexer::parsingAborted() {
+ qDebug ( "parsing aborted" );
+}
+
+void PSCommentLexer::nextStep (char c, State *newState, Action *newAction) {
+ int i=0;
+
+ while (true) {
+ Transition trans = transitions[i];
+
+ if (trans.c == STOP) {
+ *newState = trans.newState;
+ *newAction = trans.action;
+ return;
+ }
+
+ bool found = false;
+
+ if (trans.oldState == m_curState) {
+ switch (trans.c) {
+ case CATEGORY_WHITESPACE : found = isspace(c); break;
+ case CATEGORY_ALPHA : found = isalpha(c); break;
+ case CATEGORY_DIGIT : found = isdigit(c); break;
+ case CATEGORY_SPECIAL : found = isSpecial(c); break;
+ case CATEGORY_LETTERHEX : found = isletterhex(c); break;
+ case CATEGORY_INTTOOLONG : found = m_buffer.length() > MAX_INTLEN; break;
+ case CATEGORY_ANY : found = true; break;
+ default : found = (trans.c == c);
+ }
+
+ if (found) {
+ *newState = trans.newState;
+ *newAction = trans.action;
+
+ return;
+ }
+ }
+
+
+ i++;
+ }
+}
+
+uchar PSCommentLexer::decode()
+{
+ uchar value = m_temp.toString().toShort(NULL, 8);
+// qDebug ("got encoded char %c",value);
+ return value;
+}
+
+/* StringBuffer implementation */
+
+int initialSize = 20;
+int addSize = 10;
+
+StringBuffer::StringBuffer () {
+ m_buffer = (char*)calloc (initialSize, sizeof(char));
+ m_length = 0;
+ m_capacity = initialSize;
+}
+
+StringBuffer::~StringBuffer (){
+ free(m_buffer);
+}
+
+void StringBuffer::append (char c){
+ ensureCapacity(m_length + 1);
+ m_buffer[m_length] = c;
+ m_length++;
+}
+
+void StringBuffer::clear(){
+ for (uint i=0; i<m_length; i++) m_buffer[i] = '\0';
+ m_length = 0;
+}
+
+QString StringBuffer::toString() const {
+ QString ret(m_buffer);
+ return ret;
+}
+
+void StringBuffer::ensureCapacity (int p_capacity) {
+ if (m_capacity >= p_capacity) return;
+
+ int newSize = m_capacity + addSize;
+ if (p_capacity > newSize) newSize = p_capacity;
+
+ char* oldBuffer = m_buffer;
+ char *newBuffer = (char*)calloc (newSize, sizeof(char));
+ strcpy (newBuffer, m_buffer);
+ free(oldBuffer);
+ m_buffer = newBuffer;
+ m_capacity = newSize;
+}
+
+uint StringBuffer::length() {
+ return m_length;
+}
+
+double StringBuffer::toFloat() {
+ QString data = toString();
+ return data.toFloat();
+}
+
+int StringBuffer::toInt() {
+ QString data = toString();
+ return data.toInt();
+}
+
+const char *StringBuffer::latin1() {
+ return m_buffer;
+}
+
+QString StringBuffer::mid( uint index, uint len) const {
+ QString data = toString();
+ return data.mid(index,len);
+}
+
+/* BoundingBoxExtractor */
+BoundingBoxExtractor:: BoundingBoxExtractor() : m_llx(0), m_lly(0), m_urx(0), m_ury(0) {}
+BoundingBoxExtractor::~BoundingBoxExtractor() {}
+
+void BoundingBoxExtractor::gotComment (const char *value)
+{
+ QString data (value);
+ if (data.find("%BoundingBox:")==-1) return;
+
+ getRectangle (value, m_llx, m_lly, m_urx, m_ury);
+}
+
+bool BoundingBoxExtractor::getRectangle (const char* input, int &llx, int &lly, int &urx, int &ury)
+{
+ if (input == NULL) return false;
+
+ QString s(input);
+ if (s.contains ("(atend)")) return false;
+
+ QString s2 = s.remove("%BoundingBox:");
+ QStringList values = QStringList::split (" ", s2.latin1());
+ qDebug("size is %d",values.size());
+// if (values.size() < 5) return false;
+ llx = values[0].toInt();
+ lly = values[1].toInt();
+ urx = values[2].toInt();
+ ury = values[3].toInt();
+
+ return true;
+}
+
diff --git a/filters/karbon/eps/pscommentlexer.h b/filters/karbon/eps/pscommentlexer.h
new file mode 100644
index 00000000..bf155211
--- /dev/null
+++ b/filters/karbon/eps/pscommentlexer.h
@@ -0,0 +1,112 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Dirk Schnberger <dirk.schoenberger@sz-online.de>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PSCOMMENTLEXER_H
+#define PSCOMMENTLEXER_H
+
+#include <qiodevice.h>
+#include <qstring.h>
+
+/**
+ *@author Dirk Schnberger
+ */
+typedef enum {
+ State_Comment=0,
+ State_CommentEncodedChar,
+ State_Start
+} State;
+
+typedef enum {
+ Action_Copy=1,
+ Action_CopyOutput,
+ Action_Output,
+ Action_Ignore,
+ Action_Abort,
+ Action_OutputUnget,
+ Action_InitTemp,
+ Action_CopyTemp,
+ Action_DecodeUnget,
+ Action_ByteArraySpecial
+} Action;
+
+class StringBuffer {
+public:
+ StringBuffer ();
+ virtual ~StringBuffer ();
+
+ void append (char c);
+ void clear();
+ QString toString() const;
+ uint length();
+ double toFloat();
+ int toInt();
+ const char *latin1();
+ QString mid( uint index, uint len=0xffffffff) const;
+private:
+ char *m_buffer;
+ uint m_length;
+ int m_capacity;
+
+ void ensureCapacity (int p_capacity);
+};
+
+class PSCommentLexer {
+public:
+ PSCommentLexer();
+ virtual ~PSCommentLexer();
+
+ virtual bool parse (QIODevice& fin);
+private:
+ State m_curState;
+ StringBuffer m_buffer;
+ StringBuffer m_temp;
+
+ void nextStep (char c, State* newState, Action* newAction);
+
+ void doOutput ();
+ uchar decode();
+
+protected:
+ virtual void parsingStarted();
+ virtual void parsingFinished();
+ virtual void parsingAborted();
+
+ virtual void gotComment (const char *value);
+};
+
+class BoundingBoxExtractor : public PSCommentLexer
+{
+public:
+ BoundingBoxExtractor();
+ virtual ~BoundingBoxExtractor();
+
+ int llx() { return m_llx; }
+ int lly() { return m_lly; }
+ int urx() { return m_urx; }
+ int ury() { return m_ury; }
+private:
+ int m_llx, m_lly, m_urx, m_ury;
+ bool getRectangle (const char* input, int &llx, int &lly, int &urx, int &ury);
+
+protected:
+ void gotComment (const char *value);
+};
+
+#endif
+
diff --git a/filters/karbon/kontour/Makefile.am b/filters/karbon/kontour/Makefile.am
new file mode 100644
index 00000000..52d6220a
--- /dev/null
+++ b/filters/karbon/kontour/Makefile.am
@@ -0,0 +1,27 @@
+####### General stuff
+
+INCLUDES= -I$(srcdir) $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) -I$(top_srcdir)/karbon -I$(top_srcdir)/karbon/core $(all_includes)
+
+####### Files
+# Obviously you have to change "foo" (and maybe "import") to
+# reflect the name of your filter. If you have more files
+# than just fooimport.cc please add them to the _SOURCES line.
+
+kde_module_LTLIBRARIES = libkarbonkontourimport.la
+
+libkarbonkontourimport_la_SOURCES = kontourimport.cpp
+libkarbonkontourimport_la_LDFLAGS = -module $(KDE_PLUGIN)
+libkarbonkontourimport_la_LIBADD = $(KOFFICE_LIBS) ../../../karbon/libkarboncommon.la
+
+METASOURCES = AUTO
+
+service_DATA = karbon_kontour_import.desktop
+servicedir = $(kde_servicesdir)
+
+# Note: If your filter imports or exports some special file
+# which KDE doesn't have a mimetype for, yet, you'll have to
+# create a mimetype and install it using those two lines.
+# In case of doubt please ask koffice@kde.org or
+# koffice-devel@kde.org. Thanks.
+# mydata_DATA = x-foo.desktop
+# mydatadir = $(kde_mimedir)/text
diff --git a/filters/karbon/kontour/karbon_kontour_import.desktop b/filters/karbon/kontour/karbon_kontour_import.desktop
new file mode 100644
index 00000000..e18b68b8
--- /dev/null
+++ b/filters/karbon/kontour/karbon_kontour_import.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon Kontour Import Filter
+Name[af]=Karbon Kontoer In voer Filter
+Name[ar]=مِرْشَح استيراد Kontour لدى Karbon
+Name[bg]=Филтър за импортиране от Kontour в Karbon
+Name[br]=Sil enporzh Kontour evit Karbon
+Name[ca]=Filtre d'importació Kontour per a Karbon
+Name[cs]=Importní filtr Kontour pro Karbon14
+Name[cy]=Hidlen Fewnforio Kontour Karbon
+Name[da]=Karbon Kontour-importfilter
+Name[de]=Karbon14 Kontour-Importfilter
+Name[el]=Φίλτρο εισαγωγής Kontour του Karbon
+Name[eo]=Karbon-Kontour-importfiltrilo
+Name[es]=Filtro de importación a Kontour de Karbon
+Name[et]=Karboni Kontouri impordifilter
+Name[eu]=Karbon-en Konoutr inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon Kontour
+Name[fi]=Karbon Kontour -tuontisuodin
+Name[fr]=Filtre d'importation Kontour de Karbon 14
+Name[fy]=Kontour-Ymportfilter foar Karbon
+Name[ga]=Scagaire Iompórtála Karbon Kontour
+Name[gl]=Filtro de Importación de Kontour para Karbon
+Name[he]=מסנן ייבוא מ־Kontour ל־Karbon
+Name[hr]=Karbon Kontour filtar uvoza
+Name[hu]=Karbon Kontour importszűrő
+Name[is]=Karbon Kontour innflutningssía
+Name[it]=Filtro di importazione Kontour per Karbon
+Name[ja]=Karbon Kontour インポートフィルタ
+Name[km]=តម្រង​នាំចូល Kontour សម្រាប់ Karbon
+Name[lo]=ຕົວຕອງການນຳເຂົ້າຮູບແຕ້ມ K ຂອງຄາຮ໌ບອນ14
+Name[lt]=Karbon Kontour importavimo filtras
+Name[lv]=Karbon Kontour importa filtrs
+Name[ms]=Penapis Import Karbon Kontour
+Name[mt]=Filtru għall-importazzjoni ta' Kontour ġo Karbon14
+Name[nb]=Kontour-importfilter for Karbon
+Name[nds]=Kontour-Importfilter för Karbon
+Name[ne]=कार्बन रूपरेखा आयात फिल्टर
+Name[nl]= Kontour-importfilter voor Karbon
+Name[nn]=Kontour-importfilter for Karbon
+Name[pl]=Filtr importu formatu Kontour do Karbon
+Name[pt]=Filtro de Importação de Kontour para o Karbon
+Name[pt_BR]=Filtro de Importação Kontour do Karbon
+Name[ro]=Filtru importare Karbon14 pentru Kontour
+Name[ru]=Фильтр импорта рисунков Kontour в Karbon
+Name[se]=Karbon:a Kontour sisafievrridansilli
+Name[sk]=Karbon filter pre import pre Kontour
+Name[sl]=Uvozni filter Kontour za Karbon
+Name[sr]=Karbon-ов филтер за увоз из Kontour-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz Kontour-a
+Name[sv]=Karbon Kontour-importfilter
+Name[ta]= karbon Kontour இறக்குமதி வடிகட்டி
+Name[tg]=Филтри Воридоти Karbon Kontour
+Name[th]=ตัวกรองการนำเข้าภาพวาด K ของคาร์บอน14
+Name[tr]=Karbon Kontour Alma Filtresi
+Name[uk]=Фільтр імпорту файлів Kontour для Karbon
+Name[uz]=Karbon Kontour import filteri
+Name[uz@cyrillic]=Karbon Kontour импорт филтери
+Name[xh]=Isihluzi Sokurhweba se Karbon Kontour
+Name[zh_CN]=Karbon Kontour 导入过滤器
+Name[zh_TW]=Kontour Kontour 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=application/x-kontour
+X-KDE-Weight=1
+X-KDE-Library=libkarbonkontourimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/kontour/kontourimport.cpp b/filters/karbon/kontour/kontourimport.cpp
new file mode 100644
index 00000000..88d2fc4b
--- /dev/null
+++ b/filters/karbon/kontour/kontourimport.cpp
@@ -0,0 +1,323 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Sven Lppken <sven@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kontourimport.h>
+#include <KoFilterChain.h>
+#include <kgenericfactory.h>
+#include <kdebug.h>
+#include <KoUnit.h>
+#include <KoGlobal.h>
+#include <shapes/vellipse.h>
+#include <shapes/vrectangle.h>
+#include <shapes/vpolygon.h>
+#include <commands/vtransformcmd.h>
+#include <core/vpath.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <qcolor.h>
+#include <qfile.h>
+
+#define DPI 90
+
+typedef KGenericFactory<KontourImport, KoFilter> KontourImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonkontourimport, KontourImportFactory( "kofficefilters" ) )
+
+KontourImport::KontourImport(KoFilter *, const char *, const QStringList&) :
+ KoFilter(),
+ outdoc( "DOC" )
+{
+}
+
+KontourImport::~KontourImport()
+{
+
+}
+
+KoFilter::ConversionStatus KontourImport::convert(const QCString& from, const QCString& to)
+{
+ // check for proper conversion
+ if ( to != "application/x-karbon" || ( from != "application/x-kontour" && from != "application/x-killustrator") )
+ return KoFilter::NotImplemented;
+
+
+ KoStoreDevice* inpdev = m_chain->storageFile( "root", KoStore::Read );
+ if ( !inpdev )
+ {
+ kdError(30502) << "Unable to open input stream" << endl;
+ return KoFilter::StorageCreationError;
+ }
+
+ inpdoc.setContent( inpdev );
+
+ // Do the conversion!
+ convert();
+
+ KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
+ if(!out)
+ {
+ kdError(30502) << "Unable to open output file!" << endl;
+ return KoFilter::StorageCreationError;
+ }
+ QCString cstring = outdoc.toCString(); // utf-8 already
+ out->writeBlock( cstring.data(), cstring.length() );
+
+ return KoFilter::OK; // was successful
+}
+
+void
+KontourImport::parseGObject( VObject *object, const QDomElement &e )
+{
+ if( !e.attribute( "fillstyle" ).isEmpty() )
+ {
+ VFill fill;
+ int fillstyle = e.attribute( "fillstyle" ).toInt();
+ switch( fillstyle )
+ {
+ case 1:
+ {
+ fill.setType( VFill::solid );
+ QColor c;
+ c.setNamedColor( e.attribute( "fillcolor" ) );
+ VColor color( c );
+ fill.setColor( color );
+ }
+ break;
+ case 4:
+ {
+ VGradient grad;
+ // set color stops
+ grad.clearStops();
+ QColor c;
+ c.setNamedColor( e.attribute( "gradcolor1" ) );
+ VColor color( c );
+ grad.addStop( color, 0.0, 0.5 );
+ c.setNamedColor( e.attribute( "gradcolor2" ) );
+ VColor color2( c );
+ grad.addStop( color2, 1.0, 0.5 );
+ // set coords
+ KoRect bbox = object->boundingBox();
+ grad.setOrigin( KoPoint( bbox.left(), bbox.y() ) );
+ grad.setVector( KoPoint( bbox.right(), bbox.y() ) );
+ grad.setType( (VGradient::VGradientType)e.attribute( "gradstyle" ).toInt() );
+ fill.setType( VFill::grad );
+ fill.gradient() = grad;
+ }
+ break;
+ }
+ object->setFill( fill );
+ }
+ if( !e.attribute( "strokecolor" ).isEmpty() )
+ {
+ VStroke stroke;
+ int strokestyle = e.attribute( "strokestyle" ).toInt();
+ switch( strokestyle )
+ {
+ case 0: stroke.setType( VStroke::none );
+ break;
+ case 1:
+ {
+ QColor c;
+ c.setNamedColor( e.attribute( "strokecolor" ) );
+ VColor color( c );
+ stroke.setColor( color );
+ }
+ break;
+ case 2: case 3: case 4: case 5:
+ {
+ QColor c;
+ c.setNamedColor( e.attribute( "strokecolor" ) );
+ VColor color( c );
+ stroke.setColor( color );
+ VDashPattern dash;
+ QValueList<float> list;
+ switch ( strokestyle )
+ {
+ case 2: // dashed line
+ list << 10 << 5;
+ break;
+ case 3: // dotted line
+ list << 1 << 5;
+ break;
+ case 4: // dash-dot
+ list << 10 << 5 << 1 << 5;
+ break;
+ case 5: // dash-dot-dot
+ list << 10 << 5 << 1 << 5 << 1 << 5;
+ break;
+ }
+
+ dash.setArray( list );
+ stroke.dashPattern() = dash;
+ }
+ break;
+ }
+ float lineWidth = e.attribute( "linewidth" ).toFloat();
+ stroke.setLineWidth( lineWidth );
+ object->setStroke( stroke );
+ }
+ // handle matrix
+ QDomElement matrix = e.namedItem( "matrix" ).toElement();
+ QWMatrix mat( matrix.attribute( "m11" ).toDouble(),
+ matrix.attribute( "m12" ).toDouble(),
+ matrix.attribute( "m21" ).toDouble(),
+ matrix.attribute( "m22" ).toDouble(),
+ matrix.attribute( "dx" ).toDouble(),
+ matrix.attribute( "dy" ).toDouble() );
+
+ // undo y-mirroring
+ mat.scale( 1, -1 );
+ mat.translate( 0, -m_document.height() );
+ VTransformCmd trafo( 0L, mat );
+ trafo.visit( *object );
+
+}
+
+void
+KontourImport::convert()
+{
+ QDomElement docElem = inpdoc.documentElement();
+ QDomElement lay;
+ double height;
+ double width;
+ if( docElem.attribute( "version" ).toInt() == 2 )
+ {
+ lay = docElem;
+ height = lay.firstChild().namedItem( "layout" ).toElement().attribute( "height" ).toDouble();
+ width = lay.firstChild().namedItem( "layout" ).toElement().attribute( "width" ).toDouble();
+ }
+ else
+ {
+ lay = docElem.namedItem( "page" ).toElement();
+ height = lay.firstChild().toElement().attribute( "height" ).toDouble();
+ width = lay.firstChild().toElement().attribute( "width" ).toDouble();
+ }
+
+ m_document.setHeight( ( ( height / 72.0 ) * DPI ) );
+ m_document.setWidth( ( ( width / 72.0 ) * DPI ) );
+
+ parseGroup( lay.firstChild().toElement() );
+
+ outdoc = m_document.saveXML();
+}
+
+void
+KontourImport::parseGroup( const QDomElement &e )
+{
+ QDomElement b = e;
+ for( ; !b.isNull(); b = b.nextSibling().toElement() )
+ {
+ if ( b.tagName() == "rectangle" )
+ {
+ int x = b.attribute( "x" ).toInt();
+ int y = b.attribute( "y" ).toInt();
+ int width = b.attribute( "width" ).toInt();
+ int height = b.attribute( "height" ).toInt();
+ VObject *rect = new VRectangle( 0L, KoPoint( x, height + y ) , width, height );
+ QDomElement object = b.namedItem( "polyline" ).namedItem( "gobject" ).toElement();
+ parseGObject( rect, object );
+ m_document.append( rect );
+ }
+ else
+ if ( b.tagName() == "ellipse" )
+ {
+ QDomElement object = b.namedItem( "gobject" ).toElement();
+ QDomElement matrix = object.namedItem( "matrix" ).toElement();
+ /**
+ * Kontour uses a quite different way to display ellipses, so we
+ * need to calculate the values for the Karbon ellipse here
+ */
+ double left = ( b.attribute( "x" ).toDouble() + matrix.attribute( "dx" ).toInt() ) - ( b.attribute( "rx" ).toDouble() / 2 );
+ double right = left + b.attribute( "rx" ).toDouble();
+ double top = ( b.attribute( "y" ).toDouble() + matrix.attribute( "dy" ).toInt() ) - ( b.attribute( "ry" ).toDouble() / 2 );
+ double bottom = top + b.attribute( "ry" ).toDouble();
+ double height = top - bottom;
+ double width = right - left;
+ // Append the ellipse to the document
+ VObject *ellipse = new VEllipse( 0L, KoPoint( left, top ), width, height );
+ parseGObject( ellipse, object );
+ m_document.append( ellipse );
+ }
+ else if( b.tagName() == "polyline" )
+ {
+ /**
+ * Kontour is much simpler because it doesn't support curves, so
+ * we're done with connecting points with lines.
+ */
+ QDomElement point = b.firstChild().toElement();
+ VPath *path = new VPath( &m_document );
+ double x, y;
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->moveTo( KoPoint( x, y ) );
+ point = point.nextSibling().toElement();
+ for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
+ {
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->lineTo( KoPoint( x, y ) );
+ }
+ parseGObject( path, point );
+ m_document.append( path );
+ }
+ else if( b.tagName() == "polygon" )
+ {
+ QDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
+ VPath *path = new VPath( &m_document );
+ double x, y;
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->moveTo( KoPoint( x, y ) );
+ point = point.nextSibling().toElement();
+ for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
+ {
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->lineTo( KoPoint( x, y ) );
+ }
+ path->close();
+ // back to first point
+ parseGObject( path, point );
+ m_document.append( path );
+ }
+ else if( b.tagName() == "bezier" )
+ {
+ QDomElement point = b.namedItem( "polyline" ).firstChild().toElement();
+ VPath *path = new VPath( &m_document );
+ double x, y;
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->moveTo( KoPoint( x, y ) );
+ point = point.nextSibling().toElement();
+ for( ; point.tagName() != "gobject"; point = point.nextSibling().toElement() )
+ {
+ x = point.attribute( "x" ).toDouble();
+ y = point.attribute( "y" ).toDouble();
+ path->lineTo( KoPoint( x, y ) );
+ }
+ parseGObject( path, point );
+ m_document.append( path );
+ }
+ else if( b.tagName() == "group" || b.tagName() == "layer" )
+ {
+ parseGroup( b.toElement().firstChild().toElement() );
+ }
+ }
+}
+
+#include <kontourimport.moc>
diff --git a/filters/karbon/kontour/kontourimport.h b/filters/karbon/kontour/kontourimport.h
new file mode 100644
index 00000000..f227f908
--- /dev/null
+++ b/filters/karbon/kontour/kontourimport.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Sven Lppken <sven@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KONTOURIMPORT_H__
+#define __KONTOURIMPORT_H__
+
+#include <KoFilter.h>
+#include <qdom.h>
+#include <core/vdocument.h>
+
+class KontourImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ KontourImport(KoFilter *parent, const char *name, const QStringList&);
+ virtual ~KontourImport();
+
+ virtual KoFilter::ConversionStatus convert(const QCString& from, const QCString& to);
+
+protected:
+ QDomDocument inpdoc;
+ QDomDocument outdoc;
+ void convert();
+
+private:
+ void parseGObject( VObject *, const QDomElement & );
+ void parseGroup( const QDomElement & );
+ VDocument m_document;
+};
+
+#endif // __KONTOURIMPORT_H__
diff --git a/filters/karbon/msod/Makefile.am b/filters/karbon/msod/Makefile.am
new file mode 100644
index 00000000..f7191cd1
--- /dev/null
+++ b/filters/karbon/msod/Makefile.am
@@ -0,0 +1,18 @@
+####### General stuff
+
+INCLUDES= -I$(srcdir) $(KOFFICE_INCLUDES) $(all_includes)
+libkarbonmsodimport_la_LDFLAGS = -module -avoid-version -no-undefined $(all_libraries)
+libkarbonmsodimport_la_LIBADD = $(KOFFICE_LIBS) $(LIBZ)
+
+####### Files
+
+kde_module_LTLIBRARIES = libkarbonmsodimport.la
+
+libkarbonmsodimport_la_SOURCES = msodimport.cc msod.cc
+
+noinst_HEADERS = msodimport.h msod.h
+
+METASOURCES = AUTO
+
+service_DATA = karbon_msod_import.desktop
+servicedir = $(kde_servicesdir)
diff --git a/filters/karbon/msod/karbon_msod_import.desktop b/filters/karbon/msod/karbon_msod_import.desktop
new file mode 100644
index 00000000..f75aac71
--- /dev/null
+++ b/filters/karbon/msod/karbon_msod_import.desktop
@@ -0,0 +1,61 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon's MS Office Drawing Import Filter
+Name[ar]=مِرْشَح استيراد رسم MS Office الخاص بـ Karbon
+Name[bg]=Филтър за импортиране на MS Office Drawing в Karbon
+Name[br]=Sil enporzh MS Office Drawing evit Karbon's
+Name[ca]=Filtre d'importació MS Office Drawing per a Karbon
+Name[cs]=Importní filtr Kreslení MS Office pro Karbon
+Name[cy]=Hidlen Fewnforio Lluniad MS Office Karbon
+Name[da]=Karbons MS Office-tegning-importfilter
+Name[de]=Karbon14 Importfilter für Microsoft Office-Zeichnungen
+Name[el]=Φίλτρο εισαγωγής MS Office Drawning του Karbon
+Name[eo]=Filtrilo por importado de MS-Oficeja desegno al Karbon
+Name[es]=Filtro de importación dibujo de MS Office de Karbon
+Name[et]=Karboni MS Office'i joonistuste impordifilter
+Name[eu]=Karbon-en MSG Office-en marrazkien inportaziorako iragazkia
+Name[fa]=پالایۀ واردات ترسیم MS Office Karbon
+Name[fi]=Karbonin MS Office -piirros tuontisuodin
+Name[fr]=Filtre d'importation MS-Office Drawing de Karbon 14
+Name[fy]=MS Office Drawing-importfilter foar Karbon
+Name[gl]=Filtro de Importación de Debuxos de MS Office para Karbon
+Name[he]=מסנן לייבוא ציורים מ־MS Office ל־Karbon
+Name[hi]=कार्बन का एमएस ऑफ़िस ड्राइंग इम्पोर्ट फ़िल्टर
+Name[hr]=Karbon filtar uvoza za MS Office crteže
+Name[hu]=Karbon MS Office rajz importszűrő
+Name[is]=Karbon MS Office teikning innflutningssía
+Name[it]=Filtro di importazione MS Office Drawing per Karbon
+Name[ja]=Karbon MS Office Drawing インポートフィルタ
+Name[km]=តម្រង​នាំចូល​គំនូរ MS Office សម្រាប់ Karbon
+Name[lt]=Karbon's MS Office Drawing importavimo filtras
+Name[lv]=Karbon MS Office zīmējumu importa filtrs
+Name[ms]=Penapis Import MS Office Drawing Karbon
+Name[nb]=Importfilter fra MS Office-tegning til Karbon
+Name[nds]=Tekenimportfilter för Karbon
+Name[ne]=कार्बनको एमएस कार्यालय रेखाचित्र आयात फिल्टर
+Name[nl]=MS Office Drawing-importfilter voor Karbon
+Name[nn]=Importfilter frå MS Office-teikning til Karbon
+Name[pl]=Filtr importu z formatu MS Office Draw do Karbon
+Name[pt]=Filtro de Importação de Desenhos do MS Office para o Karbon
+Name[pt_BR]=Filtro de importação Desenho MS-Office para o Karbon
+Name[ro]=Filtru importare Karbon14 pentru desene MS Office
+Name[ru]=Фильтр импорта рисунков MS Office в Karbon
+Name[se]=Karbon:a MS Office-sárgun sisafievrridansilli
+Name[sk]=MS Office Drawing filter pre import pre Karbon
+Name[sl]=Uvozni filter risbe iz MS Office za Karbon
+Name[sr]=Karbon-ов филтер за увоз из MS Office Drawing-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz MS Office Drawing-a
+Name[sv]=Karbon-filter för import av MS Office-teckning
+Name[ta]=karbon 's MS Office வரைதல் இறக்குமதி வடிகட்டி
+Name[tg]=Филтри Воридоти Karbon-и MS Office Расмкашӣ
+Name[tr]=Karbon MS Office Çizim Alma Filtresi
+Name[uk]=Фільтр для імпорту малюнків MS Office у Karbon
+Name[uz]=MS Office chizmalarini Karbon'ga import qilish filteri
+Name[uz@cyrillic]=MS Office чизмаларини Karbon'га импорт қилиш филтери
+Name[zh_CN]=Karbon 的 MS Office Drawing 导入过滤器
+Name[zh_TW]=Karbon 的 MS Office 繪圖匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=image/x-msod
+X-KDE-Weight=1
+X-KDE-Library=libkarbonmsodimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/msod/msod.cc b/filters/karbon/msod/msod.cc
new file mode 100644
index 00000000..dd848c83
--- /dev/null
+++ b/filters/karbon/msod/msod.cc
@@ -0,0 +1,1340 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#include <kdebug.h>
+#include <qdatastream.h>
+#include <qfile.h>
+#include <qptrlist.h>
+#include <qpointarray.h>
+#include <qrect.h>
+#include <qsize.h>
+#include <msod.h>
+#include <zlib.h>
+
+const int Msod::s_area = 30505;
+
+Msod::Msod(
+ unsigned dpi) :
+ KWmf(dpi)
+{
+ m_dpi = dpi;
+ m_images.setAutoDelete(true);
+ m_opt = new Options(*this);
+ m_shape.data = 0L;
+ m_shape.length = 0;
+}
+
+Msod::~Msod()
+{
+ delete [] m_shape.data;
+ delete m_opt;
+}
+
+void Msod::drawShape(
+ unsigned shapeType,
+ Q_UINT32 bytes,
+ QDataStream &operands)
+{
+ static const char *funcTab[] =
+ {
+ "UNKNOWN", // Unknown
+ "RECTANGLE", // Rectangle
+ "ROUNDRECTANGLE", // Roundrectangle
+ "ELLIPSE", // Ellipse
+ "DIAMOND", // Diamond
+ "ISOCELESTRIANGLE", // Isocelestriangle
+ "RIGHTTRIANGLE", // Righttriangle
+ "PARALLELOGRAM", // Parallelogram
+ "TRAPEZOID", // Trapezoid
+ "HEXAGON", // Hexagon
+ "OCTAGON", // Octagon
+ "PLUS", // Plus
+ "STAR", // Star
+ "ARROW", // Arrow
+ "THICKARROW", // Thickarrow
+ "HOMEPLATE", // Homeplate
+ "CUBE", // Cube
+ "BALLOON", // Balloon
+ "SEAL", // Seal
+ "ARC", // Arc
+ "LINE", // Line
+ "PLAQUE", // Plaque
+ "CAN", // Can
+ "DONUT", // Donut
+ "TEXTSIMPLE", // Textsimple
+ "TEXTOCTAGON", // Textoctagon
+ "TEXTHEXAGON", // Texthexagon
+ "TEXTCURVE", // Textcurve
+ "TEXTWAVE", // Textwave
+ "TEXTRING", // Textring
+ "TEXTONCURVE", // Textoncurve
+ "TEXTONRING", // Textonring
+ "STRAIGHTCONNECTOR1", // Straightconnector1
+ "BENTCONNECTOR2", // Bentconnector2
+ "BENTCONNECTOR3", // Bentconnector3
+ "BENTCONNECTOR4", // Bentconnector4
+ "BENTCONNECTOR5", // Bentconnector5
+ "CURVEDCONNECTOR2", // Curvedconnector2
+ "CURVEDCONNECTOR3", // Curvedconnector3
+ "CURVEDCONNECTOR4", // Curvedconnector4
+ "CURVEDCONNECTOR5", // Curvedconnector5
+ "CALLOUT1", // Callout1
+ "CALLOUT2", // Callout2
+ "CALLOUT3", // Callout3
+ "ACCENTCALLOUT1", // Accentcallout1
+ "ACCENTCALLOUT2", // Accentcallout2
+ "ACCENTCALLOUT3", // Accentcallout3
+ "BORDERCALLOUT1", // bordercallout1
+ "BORDERCALLOUT2", // Bordercallout2
+ "BORDERCALLOUT3", // Bordercallout3
+ "ACCENTBORDERCALLOUT1", // Accentbordercallout1
+ "ACCENTBORDERCALLOUT2", // Accentbordercallout2
+ "ACCENTBORDERCALLOUT3", // Accentbordercallout3
+ "RIBBON", // Ribbon
+ "RIBBON2", // Ribbon2
+ "CHEVRON", // Chevron
+ "PENTAGON", // Pentagon
+ "NOSMOKING", // Nosmoking
+ "SEAL8", // Seal8
+ "SEAL16", // Seal16
+ "SEAL32", // Seal32
+ "WEDGERECTCALLOUT", // Wedgerectcallout
+ "WEDGERRECTCALLOUT", // Wedgerrectcallout
+ "WEDGEELLIPSECALLOUT", // Wedgeellipsecallout
+ "WAVE", // Wave
+ "FOLDEDCORNER", // Foldedcorner
+ "LEFTARROW", // Leftarrow
+ "DOWNARROW", // Downarrow
+ "UPARROW", // Uparrow
+ "LEFTRIGHTARROW", // Leftrightarrow
+ "UPDOWNARROW", // Updownarrow
+ "IRREGULARSEAL1", // Irregularseal1
+ "IRREGULARSEAL2", // Irregularseal2
+ "LIGHTNINGBOLT", // Lightningbolt
+ "HEART", // Heart
+ "PICTUREFRAME", // PictureFrame
+ "QUADARROW", // Quadarrow
+ "LEFTARROWCALLOUT", // Leftarrowcallout
+ "RIGHTARROWCALLOUT", // Rightarrowcallout
+ "UPARROWCALLOUT", // Uparrowcallout
+ "DOWNARROWCALLOUT", // Downarrowcallout
+ "LEFTRIGHTARROWCALLOUT", // Leftrightarrowcallout
+ "UPDOWNARROWCALLOUT", // Updownarrowcallout
+ "QUADARROWCALLOUT", // Quadarrowcallout
+ "BEVEL", // Bevel
+ "LEFTBRACKET", // Leftbracket
+ "RIGHTBRACKET", // Rightbracket
+ "LEFTBRACE", // Leftbrace
+ "RIGHTBRACE", // Rightbrace
+ "LEFTUPARROW", // Leftuparrow
+ "BENTUPARROW", // Bentuparrow
+ "BENTARROW", // Bentarrow
+ "SEAL24", // Seal24
+ "STRIPEDRIGHTARROW", // Stripedrightarrow
+ "NOTCHEDRIGHTARROW", // Notchedrightarrow
+ "BLOCKARC", // Blockarc
+ "SMILEYFACE", // Smileyface
+ "VERTICALSCROLL", // Verticalscroll
+ "HORIZONTALSCROLL", // Horizontalscroll
+ "CIRCULARARROW", // Circulararrow
+ "NOTCHEDCIRCULARARROW", // Notchedcirculararrow
+ "UTURNARROW", // Uturnarrow
+ "CURVEDRIGHTARROW", // Curvedrightarrow
+ "CURVEDLEFTARROW", // Curvedleftarrow
+ "CURVEDUPARROW", // Curveduparrow
+ "CURVEDDOWNARROW", // Curveddownarrow
+ "CLOUDCALLOUT", // Cloudcallout
+ "ELLIPSERIBBON", // Ellipseribbon
+ "ELLIPSERIBBON2", // Ellipseribbon2
+ "FLOWCHARTPROCESS", // Flowchartprocess
+ "FLOWCHARTDECISION", // Flowchartdecision
+ "FLOWCHARTINPUTOUTPUT", // Flowchartinputoutput
+ "FLOWCHARTPREDEFINEDPROCESS", // Flowchartpredefinedprocess
+ "FLOWCHARTINTERNALSTORAGE", // Flowchartinternalstorage
+ "FLOWCHARTDOCUMENT", // Flowchartdocument
+ "FLOWCHARTMULTIDOCUMENT", // Flowchartmultidocument
+ "FLOWCHARTTERMINATOR", // Flowchartterminator
+ "FLOWCHARTPREPARATION", // Flowchartpreparation
+ "FLOWCHARTMANUALINPUT", // Flowchartmanualinput
+ "FLOWCHARTMANUALOPERATION", // Flowchartmanualoperation
+ "FLOWCHARTCONNECTOR", // Flowchartconnector
+ "FLOWCHARTPUNCHEDCARD", // Flowchartpunchedcard
+ "FLOWCHARTPUNCHEDTAPE", // Flowchartpunchedtape
+ "FLOWCHARTSUMMINGJUNCTION", // Flowchartsummingjunction
+ "FLOWCHARTOR", // Flowchartor
+ "FLOWCHARTCOLLATE", // Flowchartcollate
+ "FLOWCHARTSORT", // Flowchartsort
+ "FLOWCHARTEXTRACT", // Flowchartextract
+ "FLOWCHARTMERGE", // Flowchartmerge
+ "FLOWCHARTOFFLINESTORAGE", // Flowchartofflinestorage
+ "FLOWCHARTONLINESTORAGE", // Flowchartonlinestorage
+ "FLOWCHARTMAGNETICTAPE", // Flowchartmagnetictape
+ "FLOWCHARTMAGNETICDISK", // Flowchartmagneticdisk
+ "FLOWCHARTMAGNETICDRUM", // Flowchartmagneticdrum
+ "FLOWCHARTDISPLAY", // Flowchartdisplay
+ "FLOWCHARTDELAY", // Flowchartdelay
+ "TEXTPLAINTEXT", // Textplaintext
+ "TEXTSTOP", // Textstop
+ "TEXTTRIANGLE", // Texttriangle
+ "TEXTTRIANGLEINVERTED", // Texttriangleinverted
+ "TEXTCHEVRON", // Textchevron
+ "TEXTCHEVRONINVERTED", // Textchevroninverted
+ "TEXTRINGINSIDE", // Textringinside
+ "TEXTRINGOUTSIDE", // Textringoutside
+ "TEXTARCHUPCURVE", // Textarchupcurve
+ "TEXTARCHDOWNCURVE", // Textarchdowncurve
+ "TEXTCIRCLECURVE", // Textcirclecurve
+ "TEXTBUTTONCURVE", // Textbuttoncurve
+ "TEXTARCHUPPOUR", // Textarchuppour
+ "TEXTARCHDOWNPOUR", // Textarchdownpour
+ "TEXTCIRCLEPOUR", // Textcirclepour
+ "TEXTBUTTONPOUR", // Textbuttonpour
+ "TEXTCURVEUP", // Textcurveup
+ "TEXTCURVEDOWN", // Textcurvedown
+ "TEXTCASCADEUP", // Textcascadeup
+ "TEXTCASCADEDOWN", // Textcascadedown
+ "TEXTWAVE1", // Textwave1
+ "TEXTWAVE2", // Textwave2
+ "TEXTWAVE3", // Textwave3
+ "TEXTWAVE4", // Textwave4
+ "TEXTINFLATE", // Textinflate
+ "TEXTDEFLATE", // Textdeflate
+ "TEXTINFLATEBOTTOM", // Textinflatebottom
+ "TEXTDEFLATEBOTTOM", // Textdeflatebottom
+ "TEXTINFLATETOP", // Textinflatetop
+ "TEXTDEFLATETOP", // Textdeflatetop
+ "TEXTDEFLATEINFLATE", // Textdeflateinflate
+ "TEXTDEFLATEINFLATEDEFLATE", // Textdeflateinflatedeflate
+ "TEXTFADERIGHT", // Textfaderight
+ "TEXTFADELEFT", // Textfadeleft
+ "TEXTFADEUP", // Textfadeup
+ "TEXTFADEDOWN", // Textfadedown
+ "TEXTSLANTUP", // Textslantup
+ "TEXTSLANTDOWN", // Textslantdown
+ "TEXTCANUP", // Textcanup
+ "TEXTCANDOWN", // Textcandown
+ "FLOWCHARTALTERNATEPROCESS", // Flowchartalternateprocess
+ "FLOWCHARTOFFPAGECONNECTOR", // Flowchartoffpageconnector
+ "CALLOUT90", // Callout90
+ "ACCENTCALLOUT90", // Accentcallout90
+ "BORDERCALLOUT90", // Bordercallout90
+ "ACCENTBORDERCALLOUT90", // Accentbordercallout90
+ "LEFTRIGHTUPARROW", // Leftrightuparrow
+ "SUN", // Sun
+ "MOON", // Moon
+ "BRACKETPAIR", // Bracketpair
+ "BRACEPAIR", // Bracepair
+ "SEAL4", // Seal4
+ "DOUBLEWAVE", // Doublewave
+ "ACTIONBUTTONBLANK", // Actionbuttonblank
+ "ACTIONBUTTONHOME", // Actionbuttonhome
+ "ACTIONBUTTONHELP", // Actionbuttonhelp
+ "ACTIONBUTTONINFORMATION", // Actionbuttoninformation
+ "ACTIONBUTTONFORWARDNEXT", // Actionbuttonforwardnext
+ "ACTIONBUTTONBACKPREVIOUS", // Actionbuttonbackprevious
+ "ACTIONBUTTONEND", // Actionbuttonend
+ "ACTIONBUTTONBEGINNING", // Actionbuttonbeginning
+ "ACTIONBUTTONRETURN", // Actionbuttonreturn
+ "ACTIONBUTTONDOCUMENT", // Actionbuttondocument
+ "ACTIONBUTTONSOUND", // Actionbuttonsound
+ "ACTIONBUTTONMOVIE", // Actionbuttonmovie
+ "HOSTCONTROL", // Hostcontrol
+ "TEXTBOX", // Textbox
+ };
+ struct
+ {
+ Q_UINT32 spid; // The shape id
+ union
+ {
+ Q_UINT32 info;
+ struct
+ {
+ Q_UINT32 fGroup : 1; // This shape is a group shape
+ Q_UINT32 fChild : 1; // Not a top-level shape
+ Q_UINT32 fPatriarch : 1; // This is the topmost group shape.
+ // Exactly one of these per drawing.
+ Q_UINT32 fDeleted : 1; // The shape has been deleted
+ Q_UINT32 fOleShape : 1; // The shape is an OLE object
+ Q_UINT32 fHaveMaster : 1; // Shape has a hspMaster property
+ Q_UINT32 fFlipH : 1; // Shape is flipped horizontally
+ Q_UINT32 fFlipV : 1; // Shape is flipped vertically
+ Q_UINT32 fConnector : 1; // Connector type of shape
+ Q_UINT32 fHaveAnchor : 1; // Shape has an anchor of some kind
+ Q_UINT32 fBackground : 1; // Background shape
+ Q_UINT32 fHaveSpt : 1; // Shape has a shape type property
+ Q_UINT32 reserved : 20; // Not yet used
+ } fields;
+ } grfPersistent;
+ } data;
+
+ // Scan lookup table for operation.
+
+ operands >> data.spid;
+ operands >> data.grfPersistent.info;
+ bytes -= 8;
+ kdDebug(s_area) << "shape-id: " << data.spid << " type: " << funcTab[shapeType] << " (" << shapeType << ")" <<
+ (data.grfPersistent.fields.fGroup ? " group" : "") <<
+ (data.grfPersistent.fields.fChild ? " child" : "") <<
+ (data.grfPersistent.fields.fPatriarch ? " patriarch" : "") <<
+ (data.grfPersistent.fields.fDeleted ? " deleted" : "") <<
+ (data.grfPersistent.fields.fOleShape ? " oleshape" : "") <<
+ (data.grfPersistent.fields.fHaveMaster ? " master" : "") <<
+ (data.grfPersistent.fields.fFlipH ? " flipv" : "") <<
+ (data.grfPersistent.fields.fConnector ? " connector" : "") <<
+ (data.grfPersistent.fields.fHaveAnchor ? " anchor" : "") <<
+ (data.grfPersistent.fields.fBackground ? " background" : "") <<
+ (data.grfPersistent.fields.fHaveSpt ? " spt" : "") <<
+ " operands: " << bytes << endl;
+ if (data.grfPersistent.fields.fDeleted)
+ return;
+ if ((!m_isRequiredDrawing) && (m_requestedShapeId != data.spid))
+ return;
+
+ // An active shape! Let's draw it...
+
+ switch (shapeType)
+ {
+ case 0:
+ if (m_opt->m_pVertices)
+ {
+ gotPolyline(m_dc, *m_opt->m_pVertices);
+ }
+ break;
+ case 1:
+ if (bytes > 7)
+ {
+ QPoint topLeft;
+ QSize size;
+
+ topLeft = normalisePoint(operands);
+ size = normaliseSize(operands);
+
+ QRect rect(topLeft, size);
+ QPointArray points(4);
+
+ points.setPoint(0, topLeft);
+ points.setPoint(1, rect.topRight());
+ points.setPoint(2, rect.bottomRight());
+ points.setPoint(3, rect.bottomLeft());
+ gotRectangle(m_dc, points);
+ }
+ case 20:
+ if (bytes > 7)
+ {
+ QPoint lineFrom;
+ QPoint lineTo;
+
+ lineTo = normalisePoint(operands);
+
+ QPointArray points(2);
+
+ points.setPoint(0, lineFrom);
+ points.setPoint(1, lineTo);
+ gotPolyline(m_dc, points);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void Msod::invokeHandler(
+ Header &op,
+ Q_UINT32 bytes,
+ QDataStream &operands)
+{
+ typedef void (Msod::*method)(Header &op, Q_UINT32 bytes, QDataStream &operands);
+
+ typedef struct
+ {
+ const char *name;
+ Q_UINT16 opcode;
+ method handler;
+ } opcodeEntry;
+
+ static const opcodeEntry funcTab[] =
+ {
+ { "ALIGNRULE", 0xF013, &Msod::opAlignrule },
+ { "ANCHOR", 0xF00E, &Msod::opAnchor },
+ { "ARCRULE", 0xF014, &Msod::opArcrule },
+ { "BSE", 0xF007, &Msod::opBse },
+ { "BSTORECONTAINER", 0xF001, &Msod::opBstorecontainer },
+ { "CALLOUTRULE", 0xF017, &Msod::opCalloutrule },
+ { "CHILDANCHOR", 0xF00F, &Msod::opChildanchor },
+ { "CLIENTANCHOR", 0xF010, &Msod::opClientanchor },
+ { "CLIENTDATA", 0xF011, &Msod::opClientdata },
+ { "CLIENTRULE", 0xF015, &Msod::opClientrule },
+ { "CLIENTTEXTBOX", 0xF00D, &Msod::opClienttextbox },
+ { "CLSID", 0xF016, &Msod::opClsid },
+ { "COLORMRU", 0xF11A, &Msod::opColormru },
+ { "CONNECTORRULE", 0xF012, &Msod::opConnectorrule },
+ { "DELETEDPSPL", 0xF11D, &Msod::opDeletedpspl },
+ { "DG", 0xF008, &Msod::opDg },
+ { "DGCONTAINER", 0xF002, &Msod::opDgcontainer },
+ { "DGG", 0xF006, &Msod::opDgg },
+ { "DGGCONTAINER", 0xF000, &Msod::opDggcontainer },
+ { "OLEOBJECT", 0xF11F, &Msod::opOleobject },
+ { "OPT", 0xF00B, &Msod::opOpt },
+ { "REGROUPITEMS", 0xF118, &Msod::opRegroupitems },
+ { "SELECTION", 0xF119, &Msod::opSelection },
+ { "SOLVERCONTAINER", 0xF005, &Msod::opSolvercontainer },
+ { "SP", 0xF00A, &Msod::opSp },
+ { "SPCONTAINER", 0xF004, &Msod::opSpcontainer },
+ { "SPGR", 0xF009, &Msod::opSpgr },
+ { "SPGRCONTAINER", 0xF003, &Msod::opSpgrcontainer },
+ { "SPLITMENUCOLORS", 0xF11E, &Msod::opSplitmenucolors },
+ { "TEXTBOX", 0xF00C, &Msod::opTextbox },
+ { NULL, 0, 0 },
+ { "BLIP", 0, &Msod::opBlip }
+ };
+ unsigned i;
+ method result;
+
+ // Scan lookup table for operation.
+
+ for (i = 0; funcTab[i].name; i++)
+ {
+ if (funcTab[i].opcode == op.opcode.fields.fbt)
+ {
+ break;
+ }
+ }
+
+ // Invoke handler.
+
+ result = funcTab[i].handler;
+ if (!result && (op.opcode.fields.fbt >= 0xF018) && (0xF117 >= op.opcode.fields.fbt))
+ result = funcTab[++i].handler;
+ if (!result)
+ {
+ if (funcTab[i].name)
+ kdWarning(s_area) << "invokeHandler: unsupported opcode: " <<
+ funcTab[i].name <<
+ " operands: " << bytes << endl;
+ else
+ kdWarning(s_area) << "invokeHandler: unsupported opcode: 0x" <<
+ QString::number(op.opcode.fields.fbt, 16) <<
+ " operands: " << bytes << endl;
+
+ // Skip data we cannot use.
+
+ skip(bytes, operands);
+ }
+ else
+ {
+ kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name <<
+ " operands: " << bytes << endl;
+
+ // We don't invoke the handler directly on the incoming operands, but
+ // via a temporary datastream. This adds overhead, but eliminates the
+ // need for the individual handlers to read *exactly* the right amount
+ // of data (thus speeding development, and possibly adding some
+ // future-proofing).
+
+ if (bytes)
+ {
+ QByteArray *record = new QByteArray(bytes);
+ QDataStream *body;
+
+ operands.readRawBytes(record->data(), bytes);
+ body = new QDataStream(*record, IO_ReadOnly);
+ body->setByteOrder(QDataStream::LittleEndian);
+ (this->*result)(op, bytes, *body);
+ delete body;
+ delete record;
+ }
+ else
+ {
+ QDataStream *body = new QDataStream();
+
+ (this->*result)(op, bytes, *body);
+ delete body;
+ }
+ }
+}
+
+QPoint Msod::normalisePoint(
+ QDataStream &operands)
+{
+ Q_UINT16 x;
+ Q_UINT16 y;
+
+ operands >> x >> y;
+ return QPoint(x / m_dpi, y / m_dpi);
+}
+
+QSize Msod::normaliseSize(
+ QDataStream &operands)
+{
+ Q_UINT16 width;
+ Q_UINT16 height;
+
+ operands >> width >> height;
+ return QSize(width / m_dpi, height / m_dpi);
+}
+
+bool Msod::parse(
+ unsigned shapeId,
+ const QString &file,
+ const char *delayStream)
+{
+ QFile in(file);
+ if (!in.open(IO_ReadOnly))
+ {
+ kdError(s_area) << "Unable to open input file!" << endl;
+ in.close();
+ return false;
+ }
+ QDataStream stream(&in);
+ bool result = parse(shapeId, stream, in.size(), delayStream);
+ in.close();
+ return result;
+}
+
+bool Msod::parse(
+ unsigned shapeId,
+ QDataStream &stream,
+ unsigned size,
+ const char *delayStream)
+{
+ stream.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt !
+ m_requestedShapeId = shapeId;
+ m_isRequiredDrawing = false;
+ m_delayStream = delayStream;
+
+ // Read bits.
+
+ walk(size, stream);
+ return true;
+}
+
+void Msod::opAlignrule(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opAnchor(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opArcrule(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opBlip(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ typedef enum
+ {
+ msobiWMF = 0x216, // Metafile header then compressed WMF.
+ msobiEMF = 0x3D4, // Metafile header then compressed EMF.
+ msobiPICT = 0x542, // Metafile header then compressed PICT.
+ msobiPNG = 0x6E0, // One byte tag then PNG data.
+ msobiJPEG = 0x46A, // One byte tag then JFIF data.
+ msobiDIB = 0x7A8, // One byte tag then DIB data.
+ msobiClient = 0x800 // Clients should set this bit.
+ } MSOBI;
+ typedef enum
+ {
+ msocompressionDeflate,
+ msocompressionNone = 254,
+ msocompressionTest
+ } MSOBLIPCOMPRESSION;
+
+ bool hasPrimaryId;
+ Q_UINT32 length = 0;
+ struct
+ {
+ Q_UINT32 cb;
+ struct
+ {
+ Q_UINT32 x;
+ Q_UINT32 y;
+ Q_UINT32 w;
+ Q_UINT32 h;
+ } bounds;
+ struct
+ {
+ Q_UINT32 w;
+ Q_UINT32 h;
+ } ptSize;
+ Q_UINT32 cbSave;
+ Q_UINT8 compression;
+ Q_UINT8 filter;
+ } data;
+
+ // Skip any explicit primary header (m_rgbUidprimary).
+
+ switch (m_blipType)
+ {
+ case msoblipEMF:
+ hasPrimaryId = (m_blipType ^ msobiEMF) != 0;
+ break;
+ case msoblipWMF:
+ hasPrimaryId = (m_blipType ^ msobiWMF) != 0;
+ break;
+ case msoblipPICT:
+ hasPrimaryId = (m_blipType ^ msobiPICT) != 0;
+ break;
+ case msoblipJPEG:
+ hasPrimaryId = (m_blipType ^ msobiJPEG) != 0;
+ break;
+ case msoblipPNG:
+ hasPrimaryId = (m_blipType ^ msobiPNG) != 0;
+ break;
+ case msoblipDIB:
+ hasPrimaryId = (m_blipType ^ msobiDIB) != 0;
+ break;
+ default:
+ hasPrimaryId = (m_blipType ^ msobiClient) != 0;
+ break;
+ }
+ if (hasPrimaryId)
+ {
+ length += 16;
+ skip(16, operands);
+ }
+
+ // Process the rest of the header.
+
+ data.compression = msocompressionNone;
+ switch (m_blipType)
+ {
+ case msoblipEMF:
+ case msoblipWMF:
+ case msoblipPICT:
+ length += 34;
+ operands >> data.cb;
+ operands >> data.bounds.x >> data.bounds.y >> data.bounds.w >> data.bounds.h;
+ operands >> data.ptSize.w >> data.ptSize.h;
+ operands >> data.cbSave;
+ operands >> data.compression >> data.filter;
+ break;
+ case msoblipJPEG:
+ case msoblipPNG:
+ case msoblipDIB:
+ // Skip the "tag".
+ length += 1;
+ skip(1, operands);
+ break;
+ default:
+ break;
+ }
+
+ // Work out the file type.
+
+ Image *image = new Image();
+ switch (m_blipType)
+ {
+ case msoblipEMF:
+ image->extension = "emf";
+ break;
+ case msoblipWMF:
+ image->extension = "wmf";
+ break;
+ case msoblipPICT:
+ image->extension = "pic";
+ break;
+ case msoblipJPEG:
+ image->extension = "jpg";
+ break;
+ case msoblipPNG:
+ image->extension = "png";
+ break;
+ case msoblipDIB:
+ image->extension = "dib";
+ break;
+ default:
+ image->extension = "img";
+ break;
+ }
+ image->length = bytes - length;
+ image->data = new char[image->length];
+ operands.readRawBytes((char *)image->data, image->length);
+ if (data.compression == msocompressionDeflate)
+ {
+ const char *tmp;
+ uLongf destLen = data.cb;
+ int result;
+
+ tmp = new char[data.cb];
+ result = uncompress((Q_UINT8 *)tmp, &destLen, (Q_UINT8 *)image->data, image->length);
+ if (result != Z_OK)
+ {
+ kdError(s_area) << "opBlip: uncompress failed: " << result << endl;
+ }
+ if (destLen != data.cb)
+ {
+ kdError(s_area) << "opBlip: uncompressed " << destLen << " instead of " << data.cb << endl;
+ }
+ delete [] image->data;
+ image->data = tmp;
+ image->length = destLen;
+ }
+ m_images.resize(m_images.size() + 1);
+ m_images.insert(m_images.size() - 1, image);
+}
+
+// FBSE - File Blip Store Entry
+
+void Msod::opBse(Header &op, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT8 btWin32; // Required type on Win32.
+ Q_UINT8 btMacOS; // Required type on Mac.
+ Q_UINT8 rgbUid[16]; // Identifier of blip.
+ Q_UINT16 tag; // currently unused.
+ Q_UINT32 size; // Blip size in stream.
+ Q_UINT32 cRef; // Reference count on the blip.
+ Q_UINT32 foDelay; // File offset in the delay stream.
+ Q_UINT8 usage; // How this blip is used (MSOBLIPUSAGE).
+ Q_UINT8 cbName; // length of the blip name.
+ Q_UINT8 unused2; // for the future.
+ Q_UINT8 unused3; // for the future.
+ } data;
+ unsigned i;
+
+ // Work out the type of the BLIP.
+
+ m_blipType = static_cast<MSOBLIPTYPE>(op.opcode.fields.inst);
+ operands >> data.btWin32;
+ operands >> data.btMacOS;
+ for (i = 0; i < 16; i++)
+ operands >> data.rgbUid[i];
+ operands >> data.tag >> data.size;
+ operands >> data.cRef >> data.foDelay;
+ operands >> data.usage >> data.cbName;
+ operands >> data.unused2 >> data.unused2;
+
+ // If the Blip is not in this drawing file, process it "manually".
+
+ if (m_delayStream)
+ {
+ // The m_pib refers to images by number, which includes images
+ // that are no longer here. Thus, we fake these out so that any
+ // references to non-deleted images are still valid (!!!).
+
+ if (data.size && data.cRef)
+ {
+ QByteArray bytes;
+ bytes.setRawData(m_delayStream + data.foDelay, data.size);
+ QDataStream stream(bytes, IO_ReadOnly);
+ stream.setByteOrder(QDataStream::LittleEndian);
+ walk(data.size, stream);
+ bytes.resetRawData(m_delayStream + data.foDelay, data.size);
+ }
+ else
+ {
+ m_images.resize(m_images.size() + 1);
+ m_images.insert(m_images.size() - 1, 0L);
+ }
+ }
+}
+
+void Msod::opBstorecontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+}
+
+void Msod::opCalloutrule(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opChildanchor(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opClientanchor(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 unknown;
+ } data;
+
+ operands >> data.unknown;
+ kdDebug(s_area) << "client anchor: " << data.unknown << endl;
+}
+
+void Msod::opClientdata(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 unknown;
+ } data;
+
+ operands >> data.unknown;
+ kdDebug(s_area) << "client data: " << data.unknown << endl;
+}
+
+void Msod::opClientrule(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opClienttextbox(
+ Header &,
+ Q_UINT32,
+ QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 unknown;
+ } data;
+
+ operands >> data.unknown;
+ kdDebug(s_area) << "client textbox: 0x" << QString::number(data.unknown,16) << endl;
+}
+
+void Msod::opClsid(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opColormru(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opConnectorrule(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opDeletedpspl(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+// FDG - File DG
+
+void Msod::opDg(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 csp; // The number of shapes in this drawing.
+ Q_UINT32 spidCur; // The last shape ID given to an SP in this DG.
+ } data;
+
+ operands >> data.csp >> data.spidCur;
+ kdDebug(s_area) << "drawing id: " << data.spidCur << endl;
+ m_isRequiredDrawing = (m_requestedShapeId == data.spidCur);
+ if (m_isRequiredDrawing)
+ {
+ kdDebug(s_area) << "found requested drawing" << endl;
+ }
+}
+
+void Msod::opDgcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+}
+
+// FDGG - File DGG
+
+void Msod::opDgg(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 spidMax; // The current maximum shape ID.
+ Q_UINT32 cidcl; // The number of ID clusters (FIDCLs).
+ Q_UINT32 cspSaved; // The total number of shapes saved.
+ // (including deleted shapes, if undo
+ // information was saved).
+ Q_UINT32 cdgSaved; // The total number of drawings saved.
+ } data;
+
+ // File ID Cluster - used to save IDCLs
+
+ struct
+ {
+ Q_UINT32 dgid; // DG owning the SPIDs in this cluster
+ Q_UINT32 cspidCur; // number of SPIDs used so far
+ } data1;
+ unsigned i;
+
+ operands >> data.spidMax >> data.cidcl >> data.cspSaved >> data.cdgSaved;
+ kdDebug(s_area) << data.cspSaved << " shapes in " <<
+ data.cidcl - 1 << " clusters in " <<
+ data.cdgSaved << " drawings" << endl;
+ for (i = 0; i < data.cidcl - 1; i++)
+ {
+ operands >> data1.dgid >> data1.cspidCur;
+ }
+}
+
+void Msod::opDggcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+}
+
+void Msod::opOleobject(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opOpt(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ m_opt->walk(bytes, operands);
+}
+
+void Msod::opRegroupitems(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opSelection(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::opSolvercontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+}
+
+void Msod::opSp(Header &op, Q_UINT32 bytes, QDataStream &operands)
+{
+ // We want to defer the act of drawing a shape until we have seen any options
+ // that may affect it. Thus, we merely store the data away, and let opSpContainer
+ // do all the ahrd work.
+
+ m_shape.type = op.opcode.fields.inst;
+ m_shape.length = bytes;
+ m_shape.data = new char [bytes];
+ operands.readRawBytes(m_shape.data, bytes);
+}
+
+void Msod::opSpcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+
+ // Having gathered all the information for this shape, we can now draw it.
+
+ QByteArray a;
+
+ a.setRawData(m_shape.data, m_shape.length);
+ QDataStream s(a, IO_ReadOnly);
+ s.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt !
+ drawShape(m_shape.type, m_shape.length, s);
+ a.resetRawData(m_shape.data, m_shape.length);
+ delete [] m_shape.data;
+ m_shape.data = 0L;
+}
+
+void Msod::opSpgr(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 x;
+ Q_UINT32 y;
+ Q_UINT32 w;
+ Q_UINT32 h;
+ } data;
+
+ operands >> data.x >> data.y >> data.w >> data.h;
+}
+
+void Msod::opSpgrcontainer(Header &, Q_UINT32 bytes, QDataStream &operands)
+{
+ walk(bytes, operands);
+}
+
+void Msod::opSplitmenucolors(Header &, Q_UINT32, QDataStream &operands)
+{
+ struct
+ {
+ Q_UINT32 fill;
+ Q_UINT32 line;
+ Q_UINT32 shadow;
+ Q_UINT32 threeDee;
+ } data;
+
+ operands >> data.fill >> data.line >> data.shadow >> data.threeDee;
+}
+
+void Msod::opTextbox(
+ Header &,
+ Q_UINT32,
+ QDataStream &)
+{
+}
+
+void Msod::skip(Q_UINT32 bytes, QDataStream &operands)
+{
+ if ((int)bytes < 0)
+ {
+ kdError(s_area) << "skip: " << (int)bytes << endl;
+ return;
+ }
+ if (bytes)
+ {
+ Q_UINT32 i;
+ Q_UINT8 discard;
+
+ kdDebug(s_area) << "skip: " << bytes << endl;
+ for (i = 0; i < bytes; i++)
+ {
+ operands >> discard;
+ }
+ }
+}
+
+void Msod::walk(Q_UINT32 bytes, QDataStream &operands)
+{
+ Header op;
+ Q_UINT32 length = 0;
+
+ // Stop parsing when there are no more records. Note that we stop as soon
+ // as we cannot get a complete header.
+ while (length + 8 <= bytes)
+ {
+ operands >> op.opcode.info >> op.cbLength;
+
+ // If we get some duff data, protect ourselves.
+ if (length + op.cbLength + 8 > bytes)
+ {
+ op.cbLength = bytes - length - 8;
+ }
+ length += op.cbLength + 8;
+ if (op.opcode.fields.fbt == 0x200)
+ {
+ // This appears to be an EOF marker.
+ break;
+ }
+
+ // Package the arguments...
+
+ invokeHandler(op, op.cbLength, operands);
+ }
+
+ // Eat unexpected data that the caller may expect us to consume.
+ skip(bytes - length, operands);
+}
+
+Msod::Options::Options(
+ Msod &parent) :
+ m_parent(parent)
+{
+ m_pVertices = 0L;
+ initialise();
+}
+
+Msod::Options::~Options()
+{
+ delete m_pVertices;
+}
+
+double Msod::Options::from1616ToDouble(Q_UINT32 value)
+{
+ return (value >> 16) + 65535.0 / (double)(value & 0xffff);
+}
+
+void Msod::Options::initialise()
+{
+ m_rotation = 0.0;
+
+ m_lTxid = 0;
+
+ m_pib = 0;
+ m_pibName = QString::null;
+ m_pibFlags = 0;
+ m_pictureId = 0;
+ m_fNoHitTestPicture = false;
+ m_pictureGray = false;
+ m_pictureBiLevel = false;
+ m_pictureActive = false;
+
+ m_geoLeft = 0;
+ m_geoTop = 0;
+ m_geoRight = 21600;
+ m_geoBottom = 21600;
+ m_shapePath = 1;
+ delete m_pVertices;
+ m_pVertices = 0L;
+ m_fShadowOK = true;
+ m_f3DOK = true;
+ m_fLineOK = true;
+ m_fGTextOK = false;
+ m_fFillShadeShapeOK = false;
+ m_fFillOK = true;
+
+ m_fFilled = true;
+ m_fHitTestFill = true;
+ m_fillShape = true;
+ m_fillUseRect = false;
+ m_fNoFillHitTest = false;
+
+ m_lineColor = 0;
+ m_lineBackColor = 0xffffff;
+ m_lineType = 0;
+ m_lineWidth = 9525;
+
+ m_fArrowheadsOK = false;
+ m_fLine = true;
+ m_fHitTestLine = true;
+ m_lineFillShape = true;
+ m_fNoLineDrawDash = false;
+
+ m_bWMode = 1;
+
+ m_fOleIcon = false;
+ m_fPreferRelativeResize = false;
+ m_fLockShapeType = false;
+ m_fDeleteAttachedObject = false;
+ m_fBackground = false;
+}
+
+void Msod::Options::walk(Q_UINT32 bytes, QDataStream &operands)
+{
+ Header op;
+ Q_UINT16 length = 0;
+ Q_UINT16 complexLength = 0;
+
+ // Reset all options to default values.
+
+ initialise();
+
+ // First process all simple options, and add all complex options to a list.
+
+ QPtrList<Header> complexOpts;
+ complexOpts.setAutoDelete(true);
+ bool unsupported;
+ while (length + complexLength < (int)bytes)
+ {
+ operands >> op.opcode.info >> op.value;
+ length += 6;
+
+ // Defer processing of complex options.
+
+ if (op.opcode.fields.fComplex)
+ {
+ complexLength += op.value;
+ complexOpts.append(new Header(op));
+ continue;
+ }
+
+ // Now squirrel away the option value.
+
+ unsupported = false;
+ switch (op.opcode.fields.pid)
+ {
+ case 4:
+ m_rotation = from1616ToDouble(op.value);
+ break;
+ case 128:
+ m_lTxid = op.value;
+ kdDebug(s_area) << "textbox: 0x" << QString::number(op.value,16) << endl;
+ break;
+ case 260:
+ if (op.opcode.fields.fBid)
+ {
+ m_pib = op.value;
+ if (m_parent.m_isRequiredDrawing)
+ {
+ Image *image = m_parent.m_images[m_pib - 1];
+
+ // If it is an embedded WMF we don't bother with the
+ // part; we just extract it as more vector graphics.
+
+ if (image->extension == "wmf")
+ {
+ QByteArray a;
+ a.setRawData(image->data, image->length);
+ QDataStream s(a, IO_ReadOnly);
+ m_parent.KWmf::parse(s, image->length);
+ a.resetRawData(image->data, image->length);
+ }
+ else
+ {
+ m_parent.gotPicture(
+ m_pib,
+ image->extension,
+ image->length,
+ image->data);
+ }
+ }
+ }
+ else
+ {
+ kdError(s_area) << "Cannot handle IMsoBlip" << endl;
+ }
+ break;
+ case 262:
+ m_pibFlags = op.value;
+ break;
+ case 267:
+ m_pictureId = op.value;
+ break;
+ case 319:
+ m_fNoHitTestPicture = (op.value & 0x0008) != 0;
+ m_pictureGray = (op.value & 0x0004) != 0;
+ m_pictureBiLevel = (op.value & 0x0002) != 0;
+ m_pictureActive = (op.value & 0x0001) != 0;
+ break;
+ case 320:
+ m_geoLeft = op.value;
+ break;
+ case 321:
+ m_geoTop = op.value;
+ break;
+ case 322:
+ m_geoRight = op.value;
+ break;
+ case 323:
+ m_geoBottom = op.value;
+ break;
+ case 324:
+ m_shapePath = op.value;
+ break;
+ case 383:
+ m_fShadowOK = (op.value & 0x0020) != 0;
+ m_f3DOK = (op.value & 0x0010) != 0;
+ m_fLineOK = (op.value & 0x0008) != 0;
+ m_fGTextOK = (op.value & 0x0004) != 0;
+ m_fFillShadeShapeOK = (op.value & 0x0002) != 0;
+ m_fFillOK = (op.value & 0x0001) != 0;
+ break;
+ case 447:
+ m_fFilled = (op.value & 0x0010) != 0;
+ m_fHitTestFill = (op.value & 0x0008) != 0;
+ m_fillShape = (op.value & 0x0004) != 0;
+ m_fillUseRect = (op.value & 0x0002) != 0;
+ m_fNoFillHitTest = (op.value & 0x0001) != 0;
+ break;
+ case 448:
+ m_lineColor = op.value;
+ break;
+ case 450:
+ m_lineBackColor = op.value;
+ break;
+ case 452:
+ m_lineType = op.value;
+ break;
+ case 459:
+ m_lineWidth = op.value;
+ break;
+ case 511:
+ m_fArrowheadsOK = (op.value & 0x0010) != 0;
+ m_fLine = (op.value & 0x0008) != 0;
+ m_fHitTestLine = (op.value & 0x0004) != 0;
+ m_lineFillShape = (op.value & 0x0002) != 0;
+ m_fNoLineDrawDash = (op.value & 0x0001) != 0;
+ break;
+ case 772:
+ m_bWMode = op.value;
+ break;
+ case 831:
+ m_fOleIcon = (op.value & 0x0010) != 0;
+ m_fPreferRelativeResize = (op.value & 0x0008) != 0;
+ m_fLockShapeType = (op.value & 0x0004) != 0;
+ m_fDeleteAttachedObject = (op.value & 0x0002) != 0;
+ m_fBackground = (op.value & 0x0001) != 0;
+ break;
+ default:
+ unsupported = true;
+ kdWarning(s_area) << "unsupported simple option: " <<
+ op.opcode.fields.pid << endl;
+ break;
+ }
+ if (!unsupported)
+ kdDebug(s_area) << "simple option: " <<
+ op.opcode.fields.pid << endl;
+ }
+
+ // Now empty the list of complex options.
+
+ while (complexOpts.count())
+ {
+ Q_INT16 t16;
+ unsigned i;
+
+ op = *complexOpts.getFirst();
+ complexOpts.removeFirst();
+ unsupported = false;
+ switch (op.opcode.fields.pid)
+ {
+ case 261:
+ while (true)
+ {
+ operands >> t16;
+ if (!t16)
+ break;
+ m_pibName += QChar(t16);
+ };
+ break;
+ case 325:
+ m_pVertices = new QPointArray(op.value / 4);
+ for (i = 0; i < m_pVertices->count(); i++)
+ {
+ m_pVertices->setPoint(i, m_parent.normalisePoint(operands));
+ };
+ break;
+ case 326:
+ operands >> t16;
+ i = t16;
+ operands >> t16;
+ operands >> t16;
+ m_parent.skip(i * t16, operands);
+ break;
+ default:
+ unsupported = true;
+ kdWarning(s_area) << "unsupported complex option: " <<
+ op.opcode.fields.pid << " operands: " << op.value << endl;
+ m_parent.skip(op.value, operands);
+ break;
+ }
+ if (!unsupported)
+ kdDebug(s_area) << "complex option: " <<
+ op.opcode.fields.pid << " operands: " << op.value << endl;
+ complexLength -= op.value;
+ }
+}
diff --git a/filters/karbon/msod/msod.h b/filters/karbon/msod/msod.h
new file mode 100644
index 00000000..a3dd9efe
--- /dev/null
+++ b/filters/karbon/msod/msod.h
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+
+ This is a generic parser for Microsoft Office Drawings (MSODs). The
+ specification for this is the Microsoft Office 97 Drawing File Format
+ published in MSDN. The output is a series of callbacks (a.k.a. virtual
+ functions) which the caller can override as required.
+*/
+
+#ifndef MSOD_H
+#define MSOD_H
+
+class QString;
+class QPointArray;
+#include <kwmf.h>
+#include <qptrvector.h>
+
+class Msod :
+ private KWmf
+{
+public:
+
+ // Construction.
+
+ Msod(
+ unsigned dpi);
+ virtual ~Msod();
+
+ // Called to parse the given file. We extract a drawing by shapeId.
+ // If the drawing is not found, the return value will be false.
+
+ bool parse(
+ unsigned shapeId,
+ const QString &file,
+ const char *delayStream = 0L);
+ bool parse(
+ unsigned shapeId,
+ QDataStream &stream,
+ unsigned size,
+ const char *delayStream = 0L);
+
+ typedef KWmf::DrawContext DrawContext;
+
+ // Should be protected...
+
+ void brushSet(
+ unsigned colour,
+ unsigned style);
+ void penSet(
+ unsigned colour,
+ unsigned style,
+ unsigned width);
+
+protected:
+ // Override to get results of parsing.
+
+ virtual void gotEllipse(
+ const DrawContext &dc,
+ QString type,
+ QPoint topLeft,
+ QSize halfAxes,
+ unsigned startAngle,
+ unsigned stopAngle) = 0;
+ virtual void gotPicture(
+ unsigned id,
+ QString extension,
+ unsigned length,
+ const char *data) = 0;
+ virtual void gotPolygon(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+ virtual void gotPolyline(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+ virtual void gotRectangle(
+ const DrawContext &dc,
+ const QPointArray &points) = 0;
+
+private:
+ Msod(const Msod &);
+ const Msod &operator=(const Msod &);
+
+ // Debug support.
+
+ static const int s_area;
+
+private:
+ int m_dpi;
+ DrawContext m_dc;
+ unsigned m_dggError;
+ unsigned m_requestedShapeId;
+ bool m_isRequiredDrawing;
+ const char *m_delayStream;
+ struct
+ {
+ unsigned type;
+ char *data;
+ unsigned length;
+ } m_shape;
+
+ QPoint normalisePoint(
+ QDataStream &operands);
+ QSize normaliseSize(
+ QDataStream &operands);
+ void drawShape(
+ unsigned shapeType,
+ Q_UINT32 bytes,
+ QDataStream &operands);
+
+public:
+
+ // Common Header (MSOBFH)
+ typedef struct
+ {
+ union
+ {
+ Q_UINT32 info;
+ struct
+ {
+ Q_UINT32 ver: 4;
+ Q_UINT32 inst: 12;
+ Q_UINT32 fbt: 16;
+ } fields;
+ } opcode;
+ Q_UINT32 cbLength;
+ } Header;
+
+private:
+ typedef enum
+ {
+ msoblipERROR, // An error occurred during loading.
+ msoblipUNKNOWN, // An unknown blip type.
+ msoblipEMF, // Windows Enhanced Metafile.
+ msoblipWMF, // Windows Metafile.
+ msoblipPICT, // Macintosh PICT.
+ msoblipJPEG, // JFIF.
+ msoblipPNG, // PNG.
+ msoblipDIB, // Windows DIB.
+ msoblipFirstClient = 32, // First client defined blip type.
+ msoblipLastClient = 255 // Last client defined blip type.
+ } MSOBLIPTYPE;
+
+ MSOBLIPTYPE m_blipType;
+ unsigned m_imageId;
+ class Image
+ {
+ public:
+ QString extension;
+ unsigned length;
+ const char *data;
+ Image() { data = 0L; }
+ ~Image() { delete [] data; }
+ };
+ QPtrVector<Image> m_images;
+
+ // Opcode handling and painter methods.
+
+ void walk(
+ Q_UINT32 bytes,
+ QDataStream &operands);
+ void skip(
+ Q_UINT32 bytes,
+ QDataStream &operands);
+ void invokeHandler(
+ Header &op,
+ Q_UINT32 bytes,
+ QDataStream &operands);
+
+ void opAlignrule(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opAnchor(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opArcrule(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opBlip(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opBse(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opBstorecontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opCalloutrule(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opChildanchor(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opClientanchor(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opClientdata(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opClientrule(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opClienttextbox(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opClsid(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opColormru(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opConnectorrule(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opDeletedpspl(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opDg(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opDgcontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opDgg(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opDggcontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opOleobject(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opOpt(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opRegroupitems(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSelection(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSolvercontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSp(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSpcontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSpgr(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSpgrcontainer(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opSplitmenucolors(Header &op, Q_UINT32 bytes, QDataStream &operands);
+ void opTextbox(Header &op, Q_UINT32 bytes, QDataStream &operands);
+
+ // Option handling.
+
+ class Options
+ {
+ public:
+ Options(Msod &parent);
+ ~Options();
+ void walk(
+ Q_UINT32 bytes,
+ QDataStream &operands);
+
+ double m_rotation;
+
+ Q_UINT32 m_lTxid;
+
+ Q_UINT32 m_pib;
+ QString m_pibName;
+ Q_UINT32 m_pibFlags;
+ Q_UINT32 m_pictureId;
+ bool m_fNoHitTestPicture;
+ bool m_pictureGray;
+ bool m_pictureBiLevel;
+ bool m_pictureActive;
+
+ Q_UINT32 m_geoLeft;
+ Q_UINT32 m_geoTop;
+ Q_UINT32 m_geoRight;
+ Q_UINT32 m_geoBottom;
+ Q_UINT32 m_shapePath;
+ QPointArray *m_pVertices;
+ bool m_fShadowOK;
+ bool m_f3DOK;
+ bool m_fLineOK;
+ bool m_fGTextOK;
+ bool m_fFillShadeShapeOK;
+ bool m_fFillOK;
+
+ bool m_fFilled;
+ bool m_fHitTestFill;
+ bool m_fillShape;
+ bool m_fillUseRect;
+ bool m_fNoFillHitTest;
+
+ Q_UINT32 m_lineColor;
+ Q_UINT32 m_lineBackColor;
+ Q_UINT32 m_lineType;
+ Q_UINT32 m_lineWidth;
+
+ bool m_fArrowheadsOK;
+ bool m_fLine;
+ bool m_fHitTestLine;
+ bool m_lineFillShape;
+ bool m_fNoLineDrawDash;
+
+ Q_UINT32 m_bWMode;
+
+ bool m_fOleIcon;
+ bool m_fPreferRelativeResize;
+ bool m_fLockShapeType;
+ bool m_fDeleteAttachedObject;
+ bool m_fBackground;
+
+ private:
+ Msod &m_parent;
+
+ typedef struct
+ {
+ union
+ {
+ Q_UINT16 info;
+ struct
+ {
+ Q_UINT16 pid: 14;
+ Q_UINT16 fBid: 1;
+ Q_UINT16 fComplex: 1;
+ } fields;
+ } opcode;
+ Q_UINT32 value;
+ } Header;
+
+ void initialise();
+ double from1616ToDouble(Q_UINT32 value);
+ };
+ friend class Msod::Options;
+
+ Options *m_opt;
+};
+
+#endif
diff --git a/filters/karbon/msod/msodimport.cc b/filters/karbon/msod/msodimport.cc
new file mode 100644
index 00000000..9af11181
--- /dev/null
+++ b/filters/karbon/msod/msodimport.cc
@@ -0,0 +1,313 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#include <kdebug.h>
+#include <ktempfile.h>
+#include <kmimetype.h>
+#include <kgenericfactory.h>
+#include <KoFilterChain.h>
+#include <qfile.h>
+#include <msodimport.h>
+#include <qpointarray.h>
+
+typedef KGenericFactory<MSODImport, KoFilter> MSODImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libmsodimport, MSODImportFactory( "kofficefilters" ) )
+
+const int MSODImport::s_area = 30505;
+
+MSODImport::MSODImport(
+ KoFilter *,
+ const char *,
+ const QStringList&) :
+ KoEmbeddingFilter(), Msod(100)
+{
+}
+
+MSODImport::~MSODImport()
+{
+}
+
+KoFilter::ConversionStatus MSODImport::convert( const QCString& from, const QCString& to )
+{
+ if (to != "application/x-karbon" || from != "image/x-msod")
+ return KoFilter::NotImplemented;
+
+ // Get configuration data: the shape id, and any delay stream that we were given.
+ unsigned shapeId;
+ emit commSignalShapeID( shapeId );
+ const char *delayStream = 0L;
+ emit commSignalDelayStream( delayStream );
+ kdDebug( s_area ) << "##################################################################" << endl;
+ kdDebug( s_area ) << "shape id: " << shapeId << endl;
+ kdDebug( s_area ) << "delay stream: " << delayStream << endl;
+ kdDebug( s_area ) << "##################################################################" << endl;
+/*
+ QString config = ""; // ###### FIXME: We aren't able to pass config data right now
+ QStringList args = QStringList::split(";", config);
+ unsigned i;
+
+ kdDebug(s_area) << "MSODImport::filter: config: " << config << endl;
+ for (i = 0; i < args.count(); i++)
+ {
+ if (args[i].startsWith("shape-id="))
+ {
+ shapeId = args[i].mid(9).toUInt();
+ }
+ else
+ if (args[i].startsWith("delay-stream="))
+ {
+ delayStream = (const char *)args[i].mid(13).toULong();
+ }
+ else
+ {
+ kdError(s_area) << "Invalid argument: " << args[i] << endl;
+ return KoFilter::StupidError;
+ }
+ }
+*/
+ // doc header
+ m_text = "";
+ m_text += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ m_text += "<!DOCTYPE DOC>\n";
+ m_text += "<DOC mime=\"application/x-karbon\" syntaxVersion=\"0.1\" editor=\"WMF import filter\">\n";
+ m_text += " <LAYER name=\"Layer\" visible=\"1\">\n";
+
+ if (!parse(shapeId, m_chain->inputFile(), delayStream))
+ return KoFilter::WrongFormat;
+
+ // close doc
+ m_text += " </LAYER>\n";
+ m_text += "</DOC>\n";
+
+ emit sigProgress(100);
+
+ KoStoreDevice* dev = m_chain->storageFile( "root", KoStore::Write );
+ if (!dev)
+ {
+ kdError(s_area) << "Cannot open output file" << endl;
+ return KoFilter::StorageCreationError;
+ }
+ QCString cstring ( m_text.utf8() );
+ dev->writeBlock(cstring.data(), cstring.size()-1);
+
+ return KoFilter::OK;
+}
+
+void MSODImport::gotEllipse(
+ const DrawContext &/*dc*/,
+ QString /*type*/,
+ QPoint /*topLeft*/,
+ QSize /*halfAxes*/,
+ unsigned /*startAngle*/,
+ unsigned /*stopAngle*/)
+{
+// ### TODO
+#if 0
+ m_text += "<ellipse angle1=\"" + QString::number(startAngle) +
+ "\" angle2=\"" + QString::number(stopAngle) +
+ "\" x=\"" + QString::number(topLeft.x()) +
+ "\" y=\"" + QString::number(topLeft.y()) +
+ "\" kind=\"" + type +
+ "\" rx=\"" + QString::number(halfAxes.width()) +
+ "\" ry=\"" + QString::number(halfAxes.height()) +
+ "\">\n";
+ m_text += " <gobject fillcolor=\"#" + QString::number(dc.m_brushColour, 16) +
+ "\" fillstyle=\"" + QString::number(1 /*m_winding*/) +
+ "\" linewidth=\"" + QString::number(dc.m_penWidth) +
+ "\" strokecolor=\"#" + QString::number(dc.m_penColour, 16) +
+ "\" strokestyle=\"" + QString::number(dc.m_penStyle) +
+ "\">\n";
+ m_text += " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\"/>\n";
+ m_text += " </gobject>\n";
+ m_text += "</ellipse>\n";
+#endif
+}
+
+static void toRGB(int c, double &r, double &g, double &b)
+{
+ r = (c >> 16) / 255.0;
+ g = ((c >> 8) & 0xFF) / 255.0;
+ b = (c & 0xFF) / 255.0;
+}
+
+void MSODImport::gotPicture(
+ unsigned key,
+ QString extension,
+ unsigned length,
+ const char *data)
+{
+// ### TODO
+#if 0
+ kdDebug() << "##########################################MSODImport::gotPicture" << endl;
+ kdDebug() << "MSODImport::gotPicture -- " << extension << endl;
+ if ((extension == "wmf") ||
+ (extension == "emf") ||
+ (extension == "pict"))
+ {
+ int partRef = internalPartReference( QString::number( key ) );
+
+ if (partRef == -1)
+ {
+ m_embeddeeData = data;
+ m_embeddeeLength = length;
+
+ QString srcMime( KoEmbeddingFilter::mimeTypeByExtension( extension ) );
+ if ( srcMime == KMimeType::defaultMimeType() )
+ kdWarning( s_area ) << "Couldn't determine the mimetype from the extension" << endl;
+
+ QCString destMime; // intentionally empty, the filter manager will do the rest
+ KoFilter::ConversionStatus status;
+ partRef = embedPart( srcMime.latin1(), destMime, status, QString::number( key ) );
+
+ m_embeddeeData = 0;
+ m_embeddeeLength = 0;
+
+ if ( status != KoFilter::OK ) {
+ kdWarning(s_area) << "Couldn't convert the image!" << endl;
+ return;
+ }
+ }
+ m_text += "<object url=\"" + QString::number( partRef ) + "\" mime=\"";
+ m_text += internalPartMimeType( QString::number( key ) );
+ m_text += "\" x=\"0\" y=\"0\" width=\"100\" height=\"200\"/>\n";
+ }
+ else
+ {
+ // We could not import it as a part. Try as an image.
+ KTempFile tempFile( QString::null, '.' + extension );
+ tempFile.file()->writeBlock( data, length );
+ tempFile.close();
+
+ m_text += "<pixmap src=\"" + tempFile.name() + "\">\n"
+ " <gobject fillstyle=\"0\" linewidth=\"1\" strokecolor=\"#000000\" strokestyle=\"1\">\n"
+ " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\"/>\n"
+ " </gobject>\n"
+ "</pixmap>\n";
+
+ // Note that we cannot delete the file...
+ }
+#endif
+}
+
+void MSODImport::gotPolygon(
+ const DrawContext &dc,
+ const QPointArray &points)
+{
+ kdDebug(s_area) << "MSODImport::gotPolygon" << endl;
+ kdDebug(s_area) << QString::number(dc.m_penWidth, 16) << endl;
+ kdDebug(s_area) << dc.m_penStyle << endl;
+ m_text += "<COMPOSITE>\n";
+ if( dc.m_penWidth > 0 )
+ {
+ m_text += "<STROKE lineWidth=\"1\">\n";// + QString::number(dc.m_penWidth, 16) + "\">\n";
+ double r, g, b;
+ toRGB(dc.m_penColour, r, g, b);
+ m_text += "<COLOR v1=\"" + QString::number(r) + "\" v2=\"" + QString::number(g) + "\" v3=\"" + QString::number(b) + "\" opacity=\"1\" colorSpace=\"0\" />\n";
+ m_text += "</STROKE>\n";
+ }
+ else
+ m_text += "<STROKE lineWidth=\"1\" />\n";
+ m_text += "<FILL fillRule=\"" + QString::number(dc.m_winding) + "\">\n";
+ double r, g, b;
+ toRGB(dc.m_brushColour, r, g, b);
+ m_text += "<COLOR v1=\"" + QString::number(r) + "\" v2=\"" + QString::number(g) + "\" v3=\"" + QString::number(b) + "\" opacity=\"1\" colorSpace=\"0\" />\n";
+ m_text += "</FILL>\n";
+
+ m_text += "<PATH isClosed=\"1\" >\n";
+ pointArray(points);
+ m_text += "</PATH>\n";
+ m_text += "</COMPOSITE>\n";
+}
+
+
+void MSODImport::gotPolyline(
+ const DrawContext &dc,
+ const QPointArray &points)
+{
+ kdDebug(s_area) << "MSODImport::gotPolyline" << endl;
+ return; // ### TODO
+ m_text += "<COMPOSITE>\n";
+ m_text += "<STROKE lineWidth=\"" + QString::number(dc.m_penWidth) + "\">\n";
+ m_text += "</STROKE>\n";
+ m_text += "<PATH isClosed=\"1\" >\n";
+ pointArray(points);
+ m_text += "</PATH>\n";
+ m_text += "</COMPOSITE>\n";
+}
+
+void MSODImport::gotRectangle(
+ const DrawContext &dc,
+ const QPointArray &points)
+{
+// ### TODO
+#if 0
+ QRect bounds = points.boundingRect();
+
+ m_text += "<rectangle width=\"" + QString::number(bounds.width()) +
+ "\" x=\"" + QString::number(bounds.x()) +
+ "\" y=\"" + QString::number(bounds.y()) +
+ "\" height=\"" + QString::number(bounds.height()) +
+ "\" rounding=\"0\">\n";
+ m_text += "<polyline arrow1=\"0\" arrow2=\"0\">\n";
+ pointArray(points);
+ m_text += " <gobject fillcolor=\"#" + QString::number(dc.m_brushColour, 16) +
+ "\" fillstyle=\"" + QString::number(1 /*m_winding*/) +
+ "\" linewidth=\"" + QString::number(dc.m_penWidth) +
+ "\" strokecolor=\"#" + QString::number(dc.m_penColour, 16) +
+ "\" strokestyle=\"" + QString::number(dc.m_penStyle) +
+ "\">\n";
+ m_text += " <matrix dx=\"0\" dy=\"0\" m21=\"0\" m22=\"1\" m11=\"1\" m12=\"0\"/>\n";
+ m_text += " </gobject>\n";
+ m_text += "</polyline>\n";
+ m_text += "</rectangle>\n";
+#endif
+}
+
+void MSODImport::savePartContents( QIODevice* file )
+{
+ if ( m_embeddeeData != 0 && m_embeddeeLength != 0 )
+ file->writeBlock( m_embeddeeData, m_embeddeeLength );
+}
+
+void MSODImport::pointArray(
+ const QPointArray &points)
+{
+
+ m_text += "<MOVE x=\"" + QString::number(points.point(0).x()) +
+ "\" y=\"" + QString::number(points.point(0).y()) +
+ "\" />\n";
+ kdDebug(s_area) << "\n<MOVE x=\"" + QString::number(points.point(0).x()) +
+ "\" y=\"" + QString::number(points.point(0).y()) +
+ "\" />" << endl;
+ for (unsigned int i = 1; i < points.count(); i++)
+ {
+ m_text += "<LINE x=\"" + QString::number(points.point(i).x()) +
+ "\" y=\"" + QString::number(points.point(i).y()) +
+ "\" />\n";
+ kdDebug(s_area) << "<LINE x=\"" + QString::number(points.point(i).x()) +
+ "\" y=\"" + QString::number(points.point(i).y()) +
+ "\" />" << endl;
+ }
+
+}
+
+#include <msodimport.moc>
diff --git a/filters/karbon/msod/msodimport.h b/filters/karbon/msod/msodimport.h
new file mode 100644
index 00000000..cb6aec16
--- /dev/null
+++ b/filters/karbon/msod/msodimport.h
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#ifndef MSODIMPORT_H
+#define MSODIMPORT_H
+
+#include <KoFilter.h>
+#include <msod.h>
+
+class MSODImport :
+ public KoEmbeddingFilter, protected Msod
+{
+ Q_OBJECT
+
+public:
+ MSODImport(
+ KoFilter *parent,
+ const char *name,
+ const QStringList&);
+ virtual ~MSODImport();
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+protected:
+
+ virtual void gotEllipse(
+ const DrawContext &dc,
+ QString type,
+ QPoint topLeft,
+ QSize halfAxes,
+ unsigned startAngle,
+ unsigned stopAngle);
+ virtual void gotPicture(
+ unsigned id,
+ QString extension,
+ unsigned length,
+ const char *data);
+ virtual void gotPolygon(
+ const DrawContext &dc,
+ const QPointArray &points);
+ virtual void gotPolyline(
+ const DrawContext &dc,
+ const QPointArray &points);
+ virtual void gotRectangle(
+ const DrawContext &dc,
+ const QPointArray &points);
+
+signals:
+ // Communication signals to the parent filters
+ void commSignalDelayStream( const char* delay );
+ void commSignalShapeID( unsigned int& shapeID );
+
+private:
+ virtual void savePartContents( QIODevice* file );
+
+ // Debug support.
+ static const int s_area;
+
+ void pointArray(
+ const QPointArray &points);
+ QString m_text;
+
+ // Embedded objects.
+ const char* m_embeddeeData;
+ int m_embeddeeLength;
+};
+
+#endif
diff --git a/filters/karbon/msod/status.html b/filters/karbon/msod/status.html
new file mode 100644
index 00000000..b9b2ce5d
--- /dev/null
+++ b/filters/karbon/msod/status.html
@@ -0,0 +1,153 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Karbon filters status: MSOD FILTER</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666">
+<A NAME="START">&nbsp;</A>
+
+<BR>
+<center>
+ <h1>
+ Karbon filters status: &nbsp;&nbsp;<i>MSOD - MS Office Drawing</i>
+ </h1>
+</center>
+
+<hr NOSHADE SIZE=2 WIDTH="70%">
+
+<font size="-1"><b>
+ <A HREF="#import">Import</A> |
+ <A HREF="#export">Export</A>
+</b></font>
+
+<BR><BR><BR>
+<center><a NAME="import"></a></center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%">
+
+ <tr BGCOLOR="#DDFFDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>
+ Import MSOD for Karbon<BR>
+ <BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>24 jan 2003</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Features</font></b></td>
+ <td>very basic</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Todo</font></b></td>
+ <td>many things</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">History</font></b></td>
+ <td>24 jan 2003: port to Karbon</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Authors</font></b></td>
+ <td>
+ <A HREF="mailto:srhaque@iee.org">Shaheed Haque</A>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Links</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td>
+ <td>-</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+<br><br><br>
+
+<hr NOSHADE SIZE=1>
+<br><br><br>
+
+
+<center>
+ <a NAME="export"></a>
+</center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%">
+ <tr BGCOLOR="#FFDDDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>Export Karbon to MSOD<BR><BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Features</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Todo</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">History</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Authors</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Links</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td>
+ <td>-</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+</body>
+</html>
diff --git a/filters/karbon/oodraw/Makefile.am b/filters/karbon/oodraw/Makefile.am
new file mode 100644
index 00000000..4cca1e32
--- /dev/null
+++ b/filters/karbon/oodraw/Makefile.am
@@ -0,0 +1,24 @@
+####### General stuff
+
+INCLUDES= -I$(srcdir)/../../liboofilter \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ $(all_includes)
+
+####### Files
+kde_module_LTLIBRARIES = liboodrawimport.la
+
+
+liboodrawimport_la_SOURCES = oodrawimport.cc
+liboodrawimport_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined
+liboodrawimport_la_LIBADD = ../../liboofilter/liboofilter.la \
+ ../../../karbon/libkarboncommon.la \
+ $(KOFFICE_LIBS)
+
+METASOURCES = AUTO
+
+service_DATA = karbon_oodraw_import.desktop
+
+servicedir = $(kde_servicesdir)
diff --git a/filters/karbon/oodraw/karbon_oodraw_import.desktop b/filters/karbon/oodraw/karbon_oodraw_import.desktop
new file mode 100644
index 00000000..b634ba6a
--- /dev/null
+++ b/filters/karbon/oodraw/karbon_oodraw_import.desktop
@@ -0,0 +1,63 @@
+[Desktop Entry]
+Type=Service
+Name=OpenOffice.org Draw Import Filter for Karbon14
+Name[ar]=مِرْشَح استيراد رسم OpenOffice.org لـ Karbon14
+Name[bg]=Филтър за импортиране от OpenOffice.org Draw в Karbon14
+Name[br]=Sil enporzh OpenOffice.org Draw evit Karbon14
+Name[ca]=Filtre d'importació OpenOffice.org Draw per a Karbon14
+Name[cs]=OpenOffice.org Draw importní filtr pro Karbon14
+Name[cy]=Hidlen Fewnforio OpenOffice.org Draw ar gyfer Karbon14
+Name[da]=OpenOffice.org Draw importfilter for Karbon14
+Name[de]=Karbon14 OpenOffice.org-Draw-Importfilter
+Name[el]=Φίλτρο εισαγωγής OpenOffice.org Draw για το Karbon14
+Name[eo]=OpenOffice.org desegno-importfiltrilo por Karbon14
+Name[es]=Filtro de importación de OpenOffice.org Draw para Karbon14
+Name[et]=Karbon14 OpenOffice.org Draw' impordifilter
+Name[eu]=Karbon14-en OpenOffice.org Draw-en inportaziorako iragazkia
+Name[fa]=پالایۀ واردات ترسیم OpenOffice.org برای Karbon14
+Name[fi]=OpenOffice.org-piirrostuontisuodin Karbon14:lle
+Name[fr]=Filtre d'importation OpenOffice.org Draw de Karbon14
+Name[fy]=OpenOffice.org Draw-Ymportfilter foar Karbon14
+Name[gl]=Filtro de Importación de OpenOffice.org Draw para Karbon14
+Name[he]=מסנן לייבוא מ־OpenOffice.org Draw ל־Karbon14
+Name[hi]=कार्बन 14 के लिए ओपन-ऑफ़िस.ऑर्ग आयात छननी
+Name[hr]=OpenOffice.org Draw filtar uvoza za Karbon14
+Name[hu]=OpenOffice.org Draw importszűrő a Karbon14-hez
+Name[is]=OpenOffice.org Draw innflutningssía fyrir Karbon14
+Name[it]=Filtro di importazione OpenOffice.org Draw per Karbon14
+Name[ja]=Karbon14 OpenOffice.org Draw インポートフィルタ
+Name[km]=តម្រង​នាំចូល OpenOffice.org Draw សម្រាប់ Karbon14
+Name[lt]=OpenOffice.org Draw importavimo filtras skirtas Karbon14
+Name[lv]=OpenOffice.org Draw importa filtrs priekš Karbon14
+Name[ms]=Penapis Import OpenOffice.org Draw bagi Karbon14
+Name[nb]=OpenOffice.org Draw-importfilter for Karbon14
+Name[nds]="OpenOffice.org Draw"-Importfilter för Karbon14
+Name[ne]=कार्बन१४का लागि OpenOffice.org रेखाचित्र आयात फिल्टर
+Name[nl]=OpenOffice.org Draw-importfilter voor Karbon14
+Name[nn]=OpenOffice.org Draw-importfilter for Karbon14
+Name[pl]=Filtr importu z OpenOffice.org Draw do Karbon14
+Name[pt]=Filtro de Importação de OpenOffice.org Draw para o Karbon14
+Name[pt_BR]=Filtro de Importação OpenOffice.org Draw para o Karbon14
+Name[ru]=Фильтр импорта рисунков OpenOffice.org в Karbon14
+Name[se]=Karbon14:a OpenOffice.org Draw-sisafievrridansilli
+Name[sk]=Filter pre import OpenOffice.org Draw pre Karbon14
+Name[sl]=Uvozni filter OpenOffice.org Draw za Karbon14
+Name[sr]=Karbon14-ов филтер за увоз из OpenOffice.org Draw-а
+Name[sr@Latn]=Karbon14-ov filter za uvoz iz OpenOffice.org Draw-a
+Name[sv]=OpenOffice.org Draw-importfilter för Karbon-14
+Name[ta]=open office.org வரைதல் இறக்குமதி வடிகட்டி karbon 14
+Name[tg]=Филтри Воридоти OpenOffice.org Расмкашӣ барои Karbon14
+Name[tr]=Karbon14 için OpenOffice.org Impress Alma Filtresi
+Name[uk]=Фільтр імпорту малюнків OpenOffice.org у Karbon14
+Name[uz]=Karbon14 uchun OpenOffice.org Draw import filteri
+Name[uz@cyrillic]=Karbon14 учун OpenOffice.org Draw импорт филтери
+Name[zh_CN]=Karbon14 的 OpenOffice.org Draw 导入过滤器
+Name[zh_TW]=Karbon14 的 OpenOffice.org Draw 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=application/vnd.sun.xml.draw
+X-KDE-Weight=1
+X-KDE-Library=liboodrawimport
+X-KDE-LibraryMajor=1
+X-KDE-LibraryMinor=0
+X-KDE-LibraryDependencies=
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/oodraw/oodrawimport.cc b/filters/karbon/oodraw/oodrawimport.cc
new file mode 100644
index 00000000..f52ed5b8
--- /dev/null
+++ b/filters/karbon/oodraw/oodrawimport.cc
@@ -0,0 +1,757 @@
+/* This file is part of the KDE project
+ Copyright (c) 2003 Rob Buis <buis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "oodrawimport.h"
+
+#include <math.h>
+
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include <qdir.h>
+
+#include <kzip.h>
+#include <karchive.h>
+#include <kdebug.h>
+#include <KoUnit.h>
+#include <KoPageLayout.h>
+#include <KoDocumentInfo.h>
+#include <KoDocument.h>
+#include <ooutils.h>
+#include <KoDom.h>
+
+#include <kgenericfactory.h>
+#include <KoFilterChain.h>
+#include <KoGlobal.h>
+
+#include <shapes/vellipse.h>
+#include <shapes/vrectangle.h>
+#include <shapes/vpolygon.h>
+
+#include <core/vfill.h>
+#include <core/vgroup.h>
+
+typedef KGenericFactory<OoDrawImport, KoFilter> OoDrawImportFactory;
+K_EXPORT_COMPONENT_FACTORY( liboodrawimport, OoDrawImportFactory( "kofficefilters" ) )
+
+
+OoDrawImport::OoDrawImport( KoFilter *, const char *, const QStringList & )
+ : KoFilter(),
+ m_styles( 23, true ),
+ m_styleStack( ooNS::style, ooNS::fo )
+{
+ m_styles.setAutoDelete( true );
+}
+
+OoDrawImport::~OoDrawImport()
+{
+}
+
+KoFilter::ConversionStatus OoDrawImport::convert( QCString const & from, QCString const & to )
+{
+ kdDebug() << "Entering Oodraw Import filter: " << from << " - " << to << endl;
+
+ if( from != "application/vnd.sun.xml.draw" || to != "application/x-karbon" )
+ {
+ kdWarning() << "Invalid mimetypes " << from << " " << to << endl;
+ return KoFilter::NotImplemented;
+ }
+
+ m_zip = new KZip( m_chain->inputFile() );
+
+ if ( !m_zip->open( IO_ReadOnly ) )
+ {
+ kdError(30518) << "Couldn't open the requested file "<< m_chain->inputFile() << endl;
+ delete m_zip;
+ return KoFilter::FileNotFound;
+ }
+
+ KoFilter::ConversionStatus preStatus = openFile();
+
+ if( preStatus != KoFilter::OK )
+ {
+ m_zip->close();
+ delete m_zip;
+ return preStatus;
+ }
+/*QDomDocument docinfo;
+ createDocumentInfo( docinfo );
+
+// store document info
+KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
+if( out )
+{
+QCString info = docinfo.toCString();
+//kdDebug() << " info :" << info << endl;
+// WARNING: we cannot use KoStore::write(const QByteArray&) because it gives an extra NULL character at the end.
+out->writeBlock( info , info.length() );
+}*/
+ QDomDocument docinfo;
+ createDocumentInfo( docinfo );
+ // store document info
+ KoStoreDevice* out = m_chain->storageFile( "documentinfo.xml", KoStore::Write );
+ if( out )
+ {
+ QCString info = docinfo.toCString();
+ //kdDebug(30518) << " info :" << info << endl;
+ // WARNING: we cannot use KoStore::write(const QByteArray&) because it gives an extra NULL character at the end.
+ out->writeBlock( info , info.length() );
+ }
+
+ convert();
+ QDomDocument outdoc = m_document.saveXML();
+ // add paper info, we always need custom for svg (Rob)
+ QDomElement paper = outdoc.createElement( "PAPER" );
+ outdoc.documentElement().appendChild( paper );
+ paper.setAttribute( "format", PG_CUSTOM );
+ paper.setAttribute( "width", m_document.width() );
+ paper.setAttribute( "height", m_document.height() );
+
+ // store document content
+ out = m_chain->storageFile( "maindoc.xml", KoStore::Write );
+ if( out )
+ {
+ QCString content = outdoc.toCString();
+ kdDebug() << " content :" << content << endl;
+ out->writeBlock( content , content.length() );
+ }
+ m_zip->close();
+ delete m_zip;
+
+ kdDebug() << "######################## OoDrawImport::convert done ####################" << endl;
+
+ return KoFilter::OK;
+}
+
+// Very related to OoWriterImport::createDocumentInfo
+void OoDrawImport::createDocumentInfo( QDomDocument &docinfo )
+{
+ docinfo = KoDocument::createDomDocument( "document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1" );
+
+ OoUtils::createDocumentInfo(m_meta, docinfo);
+ //kdDebug(30518) << " meta-info :" << m_meta.toCString() << endl;
+}
+
+
+// Very related to OoWriterImport::openFile()
+KoFilter::ConversionStatus OoDrawImport::openFile()
+{
+ KoFilter::ConversionStatus status = loadAndParse( "content.xml", m_content );
+ if ( status != KoFilter::OK )
+ {
+ kdError(30518) << "Content.xml could not be parsed correctly! Aborting!" << endl;
+ return status;
+ }
+
+ // We do not stop if the following calls fail.
+ QDomDocument styles;
+ loadAndParse( "styles.xml", styles );
+ loadAndParse( "meta.xml", m_meta );
+ loadAndParse( "settings.xml", m_settings );
+
+ emit sigProgress( 10 );
+ createStyleMap( styles );
+
+ return KoFilter::OK;
+}
+
+void OoDrawImport::convert()
+{
+ m_document.saveAsPath( false );
+
+ QDomElement content = m_content.documentElement();
+
+ // content.xml contains some automatic-styles that we need to store
+ QDomNode automaticStyles = KoDom::namedItemNS( content, ooNS::office, "automatic-styles" );
+ if( !automaticStyles.isNull() )
+ insertStyles( automaticStyles.toElement() );
+
+ QDomNode body = KoDom::namedItemNS( content, ooNS::office, "body" );
+ if( body.isNull() )
+ return;
+
+ // we take the settings of the first slide for the whole document.
+ QDomElement drawPage = KoDom::namedItemNS( body, ooNS::draw, "page" );
+ if( drawPage.isNull() ) // no pages? give up.
+ return;
+
+ QDomElement *master = m_styles[drawPage.attributeNS( ooNS::draw, "master-page-name", QString::null )];
+ QDomElement *style = m_styles[master->attributeNS( ooNS::style, "page-master-name", QString::null )];
+ QDomElement properties = KoDom::namedItemNS( *style, ooNS::style, "properties" ).toElement();
+
+ if( properties.isNull() )
+ {
+ m_document.setWidth( 550.0 );
+ m_document.setHeight( 841.0 );
+ }
+ else
+ {
+ m_document.setWidth( KoUnit::parseValue(properties.attributeNS( ooNS::fo, "page-width", QString::null ) ) );
+ m_document.setHeight( KoUnit::parseValue(properties.attributeNS( ooNS::fo, "page-height", QString::null ) ) );
+ }
+
+ // parse all pages
+ for( QDomNode drawPage = body.firstChild(); !drawPage.isNull(); drawPage = drawPage.nextSibling() )
+ {
+ QDomElement dp = drawPage.toElement();
+ m_styleStack.clear(); // remove all styles
+ fillStyleStack( dp );
+ //m_styleStack.setPageMark();
+
+ // set the pagetitle
+ //QDomElement titleElement = doc.createElement( "Title" );
+ //titleElement.setAttribute( "title", dp.attributeNS( "name" ) );
+ //pageTitleElement.appendChild( titleElement );
+
+ parseGroup( 0L, dp );
+ }
+}
+
+
+KoFilter::ConversionStatus OoDrawImport::loadAndParse(const QString& filename, QDomDocument& doc)
+{
+ return OoUtils::loadAndParse( filename, doc, m_zip);
+}
+
+void
+OoDrawImport::parseGroup( VGroup *parent, const QDomElement& parentobject )
+{
+ // parse all objects
+ for( QDomNode object = parentobject.firstChild(); !object.isNull(); object = object.nextSibling() )
+ {
+ QDomElement o = object.toElement();
+ if( o.namespaceURI() != ooNS::draw ) continue;
+ QString name = o.localName();
+ QString drawID = o.attributeNS( ooNS::draw, "id", QString::null );
+ VObject *obj = 0L;
+
+ if( name == "g" ) // polyline
+ {
+ storeObjectStyles( o );
+ VGroup *group = new VGroup( parent );
+ appendPen( *group );
+ appendBrush( *group );
+ obj = group;
+ parseGroup( group, o );
+ }
+ else if( name == "rect" ) // rectangle
+ {
+ storeObjectStyles( o );
+ double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
+ double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) );
+ double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
+ double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
+ int corner = static_cast<int>( KoUnit::parseValue( o.attributeNS( ooNS::draw, "corner-radius", QString::null ) ) );
+ VRectangle *rect = new VRectangle( parent, KoPoint( x, y ), w, h, corner );
+ appendPen( *rect );
+ appendBrush( *rect );
+ obj = rect;
+ }
+ else if( name == "circle" || name == "ellipse" )
+ {
+ storeObjectStyles( o );
+ double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
+ double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
+ double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
+ double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) ) - h;
+ double start = o.attributeNS( ooNS::draw, "start-angle", QString::null ).toDouble();
+ double end = o.attributeNS( ooNS::draw, "end-angle", QString::null ).toDouble();
+ QString kind = o.attributeNS( ooNS::draw, "kind", QString::null );
+ VEllipse::VEllipseType type = VEllipse::full;
+ if( !kind.isEmpty() )
+ {
+ if( kind == "section" )
+ type = VEllipse::cut;
+ else if( kind == "cut" )
+ type = VEllipse::section;
+ else if( kind == "arc" )
+ type = VEllipse::arc;
+ }
+ VEllipse *ellipse = new VEllipse( parent, KoPoint( x, y ), w, h, type, start, end );
+ appendPen( *ellipse );
+ // arc has no brush
+ if( kind != "arc" )
+ appendBrush( *ellipse );
+ obj = ellipse;
+ }
+ else if( name == "line" ) // line
+ {
+ storeObjectStyles( o );
+ VPath *line = new VPath( parent );
+ double x1 = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x1", QString::null ) );
+ double y1 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y1", QString::null ) ) );
+ double x2 = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x2", QString::null ) );
+ double y2 = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y2", QString::null ) ) );
+ line->moveTo( KoPoint( x1, y1 ) );
+ line->lineTo( KoPoint( x2, y2 ) );
+ appendPen( *line );
+ appendBrush( *line );
+ obj = line;
+ }
+ else if( name == "polyline" ) // polyline
+ {
+ storeObjectStyles( o );
+ VPath *polyline = new VPath( parent );
+ appendPoints( *polyline, o);
+ appendPen( *polyline );
+ appendBrush( *polyline );
+ obj = polyline;
+ }
+ else if( name == "polygon" ) // polygon
+ {
+ storeObjectStyles( o );
+ //VPolygon *polygon = new VPolygon( parent );
+ //polygon->load( o );
+ VPath *polygon = new VPath( parent );
+ appendPoints( *polygon, o );
+ appendPen( *polygon );
+ appendBrush( *polygon );
+ obj = polygon;
+ }
+ else if( name == "path" ) // path
+ {
+ storeObjectStyles( o );
+ VPath *path = new VPath( parent );
+ path->loadSvgPath( o.attributeNS( ooNS::svg, "d", QString::null ) );
+ KoRect rect = parseViewBox( o );
+ double x = KoUnit::parseValue( o.attributeNS( ooNS::svg, "x", QString::null ) );
+ double y = ymirror( KoUnit::parseValue( o.attributeNS( ooNS::svg, "y", QString::null ) ) );
+ double w = KoUnit::parseValue( o.attributeNS( ooNS::svg, "width", QString::null ) );
+ double h = KoUnit::parseValue( o.attributeNS( ooNS::svg, "height", QString::null ) );
+ QWMatrix mat;
+ mat.translate( x, y );
+ mat.scale( w / rect.width(), -h / rect.height() );
+ path->transform( mat );
+ appendPen( *path );
+ appendBrush( *path );
+ obj = path;
+ }
+/*else if( name == "draw:image" ) // image
+{
+storeObjectStyles( o );
+e = doc.createElement( "OBJECT" );
+e.setAttribute( "type", 0 );
+appendImage( doc, e, pictureElement, o );
+}*/
+ else
+ {
+ kdDebug() << "Unsupported object '" << name << "'" << endl;
+ continue;
+ }
+ if( parent && obj )
+ parent->append( obj );
+ else if( obj )
+ m_document.append( obj );
+ }
+}
+
+void
+OoDrawImport::appendPen( VObject &obj )
+{
+ if( m_styleStack.hasAttributeNS( ooNS::draw, "stroke" ) )
+ {
+ VStroke stroke;
+
+ if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "none" )
+ stroke.setType( VStroke::none );
+ else if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "solid" )
+ stroke.setType( VStroke::solid );
+ else if( m_styleStack.attributeNS( ooNS::draw, "stroke" ) == "dash" )
+ {
+ QValueList<float> dashes;
+ stroke.setType( VStroke::solid );
+ QString style = m_styleStack.attributeNS( ooNS::draw, "stroke-dash" );
+ if( style == "Ultrafine Dashed" ||
+ style == "Fine Dashed (var)" || style == "Dashed (var)" )
+ stroke.dashPattern().setArray( dashes << 2 << 2 );
+ else if( style == "Fine Dashed" )
+ stroke.dashPattern().setArray( dashes << 10 << 10 );
+ else if( style == "Fine Dotted" || style == "Ultrafine Dotted (var)" ||
+ style == "Line with Fine Dots" )
+ stroke.dashPattern().setArray( dashes << 2 << 10 );
+ else if( style == "3 Dashes 3 Dots (var)" || style == "Ultrafine 2 Dots 3 Dashes" )
+ stroke.dashPattern().setArray( dashes << 3 << 3 );
+ else if( style == "2 Dots 1 Dash" )
+ stroke.dashPattern().setArray( dashes << 2 << 1 );
+ }
+ if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-width" ) )
+ {
+ double lwidth = KoUnit::parseValue( m_styleStack.attributeNS( ooNS::svg, "stroke-width" ) );
+ if( lwidth == 0 )
+ lwidth = 1.0;
+ stroke.setLineWidth( lwidth );
+ }
+ if( m_styleStack.hasAttributeNS( ooNS::svg, "stroke-color" ) )
+ {
+ VColor c;
+ parseColor( c, m_styleStack.attributeNS( ooNS::svg, "stroke-color" ) );
+ stroke.setColor( c );
+ }
+
+ obj.setStroke( stroke );
+ }
+}
+
+void
+OoDrawImport::appendBrush( VObject &obj )
+{
+ if( m_styleStack.hasAttributeNS( ooNS::draw, "fill" ) )
+ {
+ const QString fill = m_styleStack.attributeNS( ooNS::draw, "fill" );
+ VFill f;
+
+ if( fill == "solid" )
+ {
+ f.setType( VFill::solid );
+ if( m_styleStack.hasAttributeNS( ooNS::draw, "fill-color" ) )
+ {
+ VColor c;
+ parseColor( c, m_styleStack.attributeNS( ooNS::draw, "fill-color" ) );
+ f.setColor( c );
+ }
+ }
+ else if( fill == "gradient" )
+ {
+ VGradient gradient;
+ gradient.clearStops();
+ gradient.setRepeatMethod( VGradient::none );
+ QString style = m_styleStack.attributeNS( ooNS::draw, "fill-gradient-name" );
+
+ QDomElement* draw = m_draws[style];
+ if( draw )
+ {
+ double border = 0.0;
+ if( draw->hasAttributeNS( ooNS::draw, "border" ) )
+ border += draw->attributeNS( ooNS::draw, "border", QString::null ).remove( '%' ).toDouble() / 100.0;
+ VColor c;
+ parseColor( c, draw->attributeNS( ooNS::draw, "start-color", QString::null ) );
+ gradient.addStop( c, border, 0.5 );
+ parseColor( c, draw->attributeNS( ooNS::draw, "end-color", QString::null ) );
+ gradient.addStop( c, 1.0, 0.5 );
+
+ QString type = draw->attributeNS( ooNS::draw, "style", QString::null );
+ if( type == "linear" || type == "axial" )
+ {
+ gradient.setType( VGradient::linear );
+ int angle = draw->attributeNS( ooNS::draw, "angle", QString::null ).toInt() / 10;
+
+ // make sure the angle is between 0 and 359
+ angle = abs( angle );
+ angle -= ( (int) ( angle / 360 ) ) * 360;
+
+ // What we are trying to do here is to find out if the given
+ // angle belongs to a horizontal, vertical or diagonal gradient.
+ int lower, upper, nearAngle = 0;
+ for ( lower = 0, upper = 45; upper < 360; lower += 45, upper += 45 )
+ {
+ if( upper >= angle )
+ {
+ int distanceToUpper = abs( angle - upper );
+ int distanceToLower = abs( angle - lower );
+ nearAngle = distanceToUpper > distanceToLower ? lower : upper;
+ break;
+ }
+ }
+ KoRect rect = obj.boundingBox();
+ KoPoint origin, vector;
+ // nearAngle should now be one of: 0, 45, 90, 135, 180...
+ kdDebug() << "nearAngle: " << nearAngle << endl;
+ if( nearAngle == 0 || nearAngle == 180 )
+ {
+ origin.setX( rect.x() + rect.width() );
+ origin.setY( rect.y() + rect.height());
+ vector.setX( rect.x() + rect.width() );
+ vector.setY( rect.y() );
+ }
+ else if( nearAngle == 90 || nearAngle == 270 )
+ {
+ origin.setX( rect.x() );
+ origin.setY( rect.y() + rect.height() );
+ vector.setX( rect.x() + rect.width() );
+ vector.setY( rect.y() + rect.height() );
+ }
+ else if( nearAngle == 45 || nearAngle == 225 )
+ {
+ origin.setX( rect.x() );
+ origin.setY( rect.y() );
+ vector.setX( rect.x() + rect.width() );
+ vector.setY( rect.y() + rect.height() );
+ }
+ else if( nearAngle == 135 || nearAngle == 315 )
+ {
+ origin.setX( rect.x() + rect.width() );
+ origin.setY( rect.y() + rect.height() );
+ vector.setX( rect.x() );
+ vector.setY( rect.y() );
+ }
+
+ gradient.setOrigin( origin );
+ gradient.setVector( vector );
+ }
+ else if( type == "radial" || type == "ellipsoid" )
+ {
+ gradient.setType( VGradient::radial );
+//else if( type == "square" || type == "rectangular" )
+//gradient.setAttribute( "type", 6 ); // rectangle
+//else if( type == "axial" )
+//gradient.setAttribute( "type", 7 ); // pipecross
+
+ // Hard to map between x- and y-center settings of oodraw
+ // and (un-)balanced settings of kpresenter. Let's try it.
+ double x, y;
+ if( draw->hasAttributeNS( ooNS::draw, "cx" ) )
+ x = draw->attributeNS( ooNS::draw, "cx", QString::null ).remove( '%' ).toDouble() / 100.0;
+ else
+ x = 0.5;
+
+ if( draw->hasAttributeNS( ooNS::draw, "cy" ) )
+ y = draw->attributeNS( ooNS::draw, "cy", QString::null ).remove( '%' ).toDouble() / 100.0;
+ else
+ y = 0.5;
+
+ KoRect rect = obj.boundingBox();
+ gradient.setOrigin( KoPoint( rect.x() + x * rect.width(),
+ rect.y() + y * rect.height() ) );
+ gradient.setFocalPoint( KoPoint( rect.x() + x * rect.width(),
+ rect.y() + y * rect.height() ) );
+ gradient.setVector( KoPoint( rect.x() + rect.width(),
+ rect.y() + y * rect.height() ) );
+ }
+ f.gradient() = gradient;
+ f.setType( VFill::grad );
+ }
+ }
+ obj.setFill( f );
+ }
+/*else if( fill == "hatch" )
+{
+QDomElement brush = doc.createElement( "BRUSH" );
+QString style = m_styleStack.attributeNS( "fill-hatch-name" );
+if( style == "Black 0 Degrees" )
+brush.setAttribute( "style", 9 );
+else if( style == "Black 90 Degrees" )
+brush.setAttribute( "style", 10 );
+else if( style == "Red Crossed 0 Degrees" || style == "Blue Crossed 0 Degrees" )
+brush.setAttribute( "style", 11 );
+else if( style == "Black 45 Degrees" || style == "Black 45 Degrees Wide" )
+brush.setAttribute( "style", 12 );
+else if( style == "Black -45 Degrees" )
+brush.setAttribute( "style", 13 );
+else if( style == "Red Crossed 45 Degrees" || style == "Blue Crossed 45 Degrees" )
+brush.setAttribute( "style", 14 );
+
+QDomElement* draw = m_draws[style];
+if( draw && draw->hasAttributeNS( "color" ) )
+brush.setAttribute( "color", draw->attributeNS( "color" ) );
+e.appendChild( brush );
+}*/
+}
+
+void
+OoDrawImport::createStyleMap( QDomDocument &docstyles )
+{
+ QDomElement styles = docstyles.documentElement();
+ if( styles.isNull() )
+ return;
+
+ QDomNode fixedStyles = KoDom::namedItemNS( styles, ooNS::office, "styles" );
+ if( !fixedStyles.isNull() )
+ {
+ insertDraws( fixedStyles.toElement() );
+ insertStyles( fixedStyles.toElement() );
+ }
+ QDomNode automaticStyles = KoDom::namedItemNS( styles, ooNS::office, "automatic-styles" );
+ if( !automaticStyles.isNull() )
+ insertStyles( automaticStyles.toElement() );
+
+ QDomNode masterStyles = KoDom::namedItemNS( styles, ooNS::office, "master-styles" );
+ if( !masterStyles.isNull() )
+ insertStyles( masterStyles.toElement() );
+}
+
+void
+OoDrawImport::insertDraws( const QDomElement& styles )
+{
+ for( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if( !e.hasAttributeNS( ooNS::draw, "name" ) )
+ continue;
+
+ QString name = e.attributeNS( ooNS::draw, "name", QString::null );
+ m_draws.insert( name, new QDomElement( e ) );
+ }
+}
+
+
+void
+OoDrawImport::insertStyles( const QDomElement& styles )
+{
+ for ( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+
+ if( !e.hasAttributeNS( ooNS::style, "name" ) )
+ continue;
+
+ QString name = e.attributeNS( ooNS::style, "name", QString::null );
+ m_styles.insert( name, new QDomElement( e ) );
+ //kdDebug() << "Style: '" << name << "' loaded " << endl;
+ }
+}
+
+void
+OoDrawImport::fillStyleStack( const QDomElement& object )
+{
+ // find all styles associated with an object and push them on the stack
+ if( object.hasAttributeNS( ooNS::presentation, "style-name" ) )
+ addStyles( m_styles[object.attributeNS( ooNS::presentation, "style-name", QString::null )] );
+
+ if( object.hasAttributeNS( ooNS::draw, "style-name" ) )
+ addStyles( m_styles[object.attributeNS( ooNS::draw, "style-name", QString::null )] );
+
+ if( object.hasAttributeNS( ooNS::draw, "text-style-name" ) )
+ addStyles( m_styles[object.attributeNS( ooNS::draw, "text-style-name", QString::null )] );
+
+ if( object.hasAttributeNS( ooNS::text, "style-name" ) )
+ addStyles( m_styles[object.attributeNS( ooNS::text, "style-name", QString::null )] );
+}
+
+void
+OoDrawImport::addStyles( const QDomElement* style )
+{
+ // this function is necessary as parent styles can have parents themself
+ if( style->hasAttributeNS( ooNS::style, "parent-style-name" ) )
+ addStyles( m_styles[style->attributeNS( ooNS::style, "parent-style-name", QString::null )] );
+
+ m_styleStack.push( *style );
+}
+
+void
+OoDrawImport::storeObjectStyles( const QDomElement& object )
+{
+ //m_styleStack.clearPageMark(); // remove styles of previous object
+ fillStyleStack( object );
+ //m_styleStack.setObjectMark();
+}
+
+KoRect
+OoDrawImport::parseViewBox( const QDomElement& object )
+{
+ KoRect rect;
+ if( !object.attributeNS( ooNS::svg, "viewBox", QString::null ).isEmpty() )
+ {
+ // allow for viewbox def with ',' or whitespace
+ QString viewbox( object.attributeNS( ooNS::svg, "viewBox", QString::null ) );
+ QStringList points = QStringList::split( ' ', viewbox.replace( ',', ' ').simplifyWhiteSpace() );
+
+ rect.setX( points[0].toFloat() );
+ rect.setY( points[1].toFloat() );
+ rect.setWidth( points[2].toFloat() );
+ rect.setHeight( points[3].toFloat() );
+ }
+ return rect;
+}
+
+void
+OoDrawImport::appendPoints(VPath &path, const QDomElement& object)
+{
+ double x = KoUnit::parseValue( object.attributeNS( ooNS::svg, "x", QString::null ) );
+ double y = KoUnit::parseValue( object.attributeNS( ooNS::svg, "y", QString::null ) );
+ double w = KoUnit::parseValue( object.attributeNS( ooNS::svg, "width", QString::null ) );
+ double h = KoUnit::parseValue( object.attributeNS( ooNS::svg, "height", QString::null ) );
+
+ KoRect rect = parseViewBox( object );
+ rect.setX( rect.x() + x );
+ rect.setY( rect.y() + y );
+
+ QStringList ptList = QStringList::split( ' ', object.attributeNS( ooNS::draw, "points", QString::null ) );
+
+ QString pt_x, pt_y;
+ double tmp_x, tmp_y;
+ KoPoint point;
+ bool bFirst = true;
+ for( QStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it )
+ {
+ tmp_x = rect.x() + ( (*it).section( ',', 0, 0 ).toInt() * w ) / rect.width();
+ tmp_y = rect.y() + ( (*it).section( ',', 1, 1 ).toInt() * h ) / rect.height();
+
+ point.setX( tmp_x );
+ point.setY( ymirror( tmp_y ) );
+ if( bFirst )
+ {
+ path.moveTo( point );
+ bFirst = false;
+ }
+ else
+ path.lineTo( point );
+ }
+}
+
+void
+OoDrawImport::parseColor( VColor &color, const QString &s )
+{
+ if( s.startsWith( "rgb(" ) )
+ {
+ QString parse = s.stripWhiteSpace();
+ QStringList colors = QStringList::split( ',', parse );
+ QString r = colors[0].right( ( colors[0].length() - 4 ) );
+ QString g = colors[1];
+ QString b = colors[2].left( ( colors[2].length() - 1 ) );
+
+ if( r.contains( "%" ) )
+ {
+ r = r.left( r.length() - 1 );
+ r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( g.contains( "%" ) )
+ {
+ g = g.left( g.length() - 1 );
+ g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( b.contains( "%" ) )
+ {
+ b = b.left( b.length() - 1 );
+ b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
+ }
+
+ QColor c( r.toInt(), g.toInt(), b.toInt() );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+ else
+ {
+ QString rgbColor = s.stripWhiteSpace();
+ QColor c;
+ if( rgbColor.startsWith( "#" ) )
+ c.setNamedColor( rgbColor );
+ //else
+ // c = parseColor( rgbColor );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+}
+
+double
+OoDrawImport::ymirror( double y )
+{
+ return m_document.height() - y;
+}
+
+#include "oodrawimport.moc"
diff --git a/filters/karbon/oodraw/oodrawimport.h b/filters/karbon/oodraw/oodrawimport.h
new file mode 100644
index 00000000..06e664ac
--- /dev/null
+++ b/filters/karbon/oodraw/oodrawimport.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ Copyright (c) 2003 Rob Buis <buis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef OODRAW_IMPORT_H__
+#define OODRAW_IMPORT_H__
+
+#include <KoFilter.h>
+#include <KoStore.h>
+
+#include <qdom.h>
+#include <qdict.h>
+#include <qcolor.h>
+#include <KoStyleStack.h>
+#include <core/vdocument.h>
+#include <core/vcomposite.h>
+#include <core/vstroke.h>
+
+class KZip;
+
+class VGroup;
+
+class OoDrawImport : public KoFilter
+{
+ Q_OBJECT
+public:
+ OoDrawImport( KoFilter *parent, const char *name, const QStringList & );
+ virtual ~OoDrawImport();
+
+ virtual KoFilter::ConversionStatus convert( QCString const & from, QCString const & to );
+
+private:
+ void createDocumentInfo( QDomDocument &docinfo );
+
+ void createStyleMap( QDomDocument &docstyles );
+ void insertStyles( const QDomElement& styles );
+ void insertDraws( const QDomElement& styles );
+ void fillStyleStack( const QDomElement& object );
+ void addStyles( const QDomElement* style );
+ void storeObjectStyles( const QDomElement& object );
+ void appendPen( VObject &obj );
+ void appendBrush( VObject &obj );
+ void appendPoints(VPath &path, const QDomElement& object);
+ void convert();
+ void parseGroup( VGroup *parent, const QDomElement& object );
+ void parseColor( VColor &color, const QString &s );
+ double ymirror( double y );
+ KoRect parseViewBox( const QDomElement& object );
+
+ KoFilter::ConversionStatus openFile();
+ KoFilter::ConversionStatus loadAndParse(const QString& filename, QDomDocument& doc);
+
+ VDocument m_document;
+ QDomDocument m_content;
+ QDomDocument m_meta;
+ QDomDocument m_settings;
+ QDict<QDomElement> m_styles, m_draws;
+ KoStyleStack m_styleStack;
+ KZip * m_zip;
+
+};
+
+#endif
diff --git a/filters/karbon/png/Makefile.am b/filters/karbon/png/Makefile.am
new file mode 100644
index 00000000..5d8a4efb
--- /dev/null
+++ b/filters/karbon/png/Makefile.am
@@ -0,0 +1,27 @@
+kde_module_LTLIBRARIES = libkarbonpngexport.la
+
+libkarbonpngexport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonpngexport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/render \
+ -I$(top_srcdir)/karbon/visitors \
+ $(all_includes)
+
+service_DATA = karbon_png_export.desktop
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ pngexport.h
+
+libkarbonpngexport_la_SOURCES = \
+ pngexport.cc
+
+libkarbonpngexport_la_METASOURCES = \
+ AUTO
+
diff --git a/filters/karbon/png/karbon_png_export.desktop b/filters/karbon/png/karbon_png_export.desktop
new file mode 100644
index 00000000..e3715bc0
--- /dev/null
+++ b/filters/karbon/png/karbon_png_export.desktop
@@ -0,0 +1,67 @@
+[Desktop Entry]
+Icon=
+Name=Karbon14 PNG Export Filter
+Name[af]=Karbon14 Png Voer uit Filter
+Name[ar]=مِرْشَح تصدير PNG لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в PNG
+Name[br]=Sil ezporzh PNG evit Karbon14
+Name[ca]=Filtre d'exportació PNG per a Karbon14
+Name[cs]=Exportní filtr do formátu PNG pro Karbon14
+Name[cy]=Hidlen Allforio PNG Karbon14
+Name[da]=Karbon14 SVG-eksportfilter
+Name[de]=Karbon14 PNG-Exportfilter
+Name[el]=Φίλτρο εξαγωγής PNG του Karbon14
+Name[eo]=Karbon-PNG-eksportfiltrilo
+Name[es]=Filtro de exportación Karbon14 PNG
+Name[et]=Karbon14 PNG ekspordifilter
+Name[eu]=Karbon14-en PNG esportaziorako iragazkia
+Name[fa]=پالایۀ صادرات Karbon14 PNG
+Name[fi]=Karbon14 PNG -vientisuodin
+Name[fr]=Filtre d'exportation PNG de Karbon 14
+Name[fy]=PNG-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála PNG Karbon14
+Name[gl]=Filtro de Exportación de PNG para Karbon14
+Name[he]=מסנן ייצוא מ־Karbon14 ל־PNG
+Name[hr]=Karbon14 SVG filtar izvoza
+Name[hu]=Karbon14 PNG exportszűrő
+Name[is]=Karbon14 PNG útflutningssía
+Name[it]=Filtro di esportazione PNG per Karbon14
+Name[ja]=Karbon14 PNG エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ PNG សម្រាប់ Karbon14
+Name[lo]=ຕົວຕອງການສົ່ງອອກ PNG ຂອງ Karbon14
+Name[lt]=Karbon14 PNG eksportavimo filtras
+Name[lv]=Karbon14 PNG eksporta filtrs
+Name[ms]=Penapis Eksport Karbon14 PNG
+Name[mt]=Filtru għall-esportazzjoni ta' PNG minn ġo Karbon14
+Name[nb]=PNG-eksportfilter for Karbon14
+Name[nds]=PNG-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ पीएनजी निर्यात फिल्टर
+Name[nl]=PNG-exportfilter voor Karbon14
+Name[nn]=PNG-eksportfilter for Karbon14
+Name[pl]=Filtr eksportu do formatu PNG z Karbon14
+Name[pt]=Filtro de Exportação de PNG para o Karbon14
+Name[pt_BR]=Filtro de Exportação PNG do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru SVG
+Name[ru]=Фильтр экспорта рисунков Karbon в PNG
+Name[se]=Karbon14:a PNG-olggosfievrridansilli
+Name[sk]=PNG filter pre export z Karbon14
+Name[sl]=Izvozni filter PNG za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у PNG
+Name[sr@Latn]=Karbon14-ov filter za izvoz u PNG
+Name[sv]=Karbon14 PNG-exportfilter
+Name[ta]=Karbon 14 PNG S ஏற்றுமதி வடிகட்டி
+Name[tg]=Karbon14 PNG Филтри Содирот
+Name[th]=ตัวกรองการส่งออก PNG ของ Karbon14
+Name[tr]=Karbon14 PNG Aktarma Filtresi
+Name[uk]=Фільтр експорту SVG для Karbon14
+Name[uz]=Karbon14 PNG eksport filteri
+Name[uz@cyrillic]=Karbon14 PNG экспорт филтери
+Name[xh]=Isihluzi Sokurhweba ngaphandle se Karbon14 PNG
+Name[zh_CN]=Karbon14 PNG 导出过滤器
+Name[zh_TW]=Karbon14 EPS 匯出過濾程式
+ServiceTypes=KOfficeFilter
+Type=Service
+X-KDE-Export=image/png
+X-KDE-Import=application/x-karbon
+X-KDE-Library=libkarbonpngexport
+X-KDE-Weight=1
diff --git a/filters/karbon/png/pngexport.cc b/filters/karbon/png/pngexport.cc
new file mode 100644
index 00000000..652074e9
--- /dev/null
+++ b/filters/karbon/png/pngexport.cc
@@ -0,0 +1,96 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcstring.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qimage.h>
+
+#include <kgenericfactory.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include "pngexport.h"
+#include "vdocument.h"
+#include "vselection.h"
+#include "vkopainter.h"
+#include "vlayer.h"
+#include "vcomputeboundingbox.h"
+
+#include <kdebug.h>
+
+
+typedef KGenericFactory<PngExport, KoFilter> PngExportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonpngexport, PngExportFactory( "kofficefilters" ) )
+
+
+PngExport::PngExport( KoFilter*, const char*, const QStringList& )
+ : KoFilter()
+{
+}
+
+KoFilter::ConversionStatus
+PngExport::convert( const QCString& from, const QCString& to )
+{
+ if ( to != "image/png" || from != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+ if( !storeIn )
+ return KoFilter::StupidError;
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ // load the document and export it:
+ VDocument doc;
+ doc.load( docNode );
+
+ // calculate the documents bounding box
+ VComputeBoundingBox bbox( true );
+ doc.accept( bbox );
+ const KoRect &rect = bbox.boundingRect();
+
+ // create image with correct width and height
+ QImage img( int( rect.width() ), int( rect.height() ), 32 );
+ //img.setAlphaBuffer( true );
+
+ // Create painter and set up objects to draw
+ VKoPainter p( img.bits(), rect.width(), rect.height() );
+ p.clear( qRgba( 0xFF, 0xFF, 0xFF, 0xFF ) );
+ p.setWorldMatrix( QWMatrix().translate( -rect.x(), -rect.y() ) );
+
+ doc.draw( &p, &rect );
+
+ QImage image = img.swapRGB();
+ QImage mirrored = image.mirror( false, true );
+ // save png
+ mirrored.save( m_chain->outputFile(), "PNG" );
+
+ return KoFilter::OK;
+}
+
+#include "pngexport.moc"
+
diff --git a/filters/karbon/png/pngexport.h b/filters/karbon/png/pngexport.h
new file mode 100644
index 00000000..a14e81c8
--- /dev/null
+++ b/filters/karbon/png/pngexport.h
@@ -0,0 +1,39 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __PNGEXPORT_H__
+#define __PNGEXPORT_H__
+
+#include <KoFilter.h>
+
+#include "vvisitor.h"
+
+class PngExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ PngExport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~PngExport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+};
+
+#endif
+
diff --git a/filters/karbon/svg/Makefile.am b/filters/karbon/svg/Makefile.am
new file mode 100644
index 00000000..a1b01f9b
--- /dev/null
+++ b/filters/karbon/svg/Makefile.am
@@ -0,0 +1,34 @@
+kde_module_LTLIBRARIES = libkarbonsvgexport.la libkarbonsvgimport.la
+
+libkarbonsvgexport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonsvgexport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+libkarbonsvgimport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonsvgimport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/visitors \
+ $(all_includes)
+
+service_DATA = karbon_svg_export.desktop karbon_svg_import.desktop
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ svgexport.h
+
+libkarbonsvgexport_la_SOURCES = \
+ svgexport.cc
+
+METASOURCES = AUTO
+
+libkarbonsvgimport_la_SOURCES = \
+ svgimport.cc
+
diff --git a/filters/karbon/svg/TODO b/filters/karbon/svg/TODO
new file mode 100644
index 00000000..999f37a6
--- /dev/null
+++ b/filters/karbon/svg/TODO
@@ -0,0 +1,8 @@
+SVG export
+- patterns
+- text
+
+SVG import
+- units (cm, mm)
+- trafo's
+- fix text
diff --git a/filters/karbon/svg/color.h b/filters/karbon/svg/color.h
new file mode 100644
index 00000000..bfdc93c6
--- /dev/null
+++ b/filters/karbon/svg/color.h
@@ -0,0 +1,306 @@
+
+#define TORGB( red, green, blue ) \
+{ \
+ r = red; \
+ b = blue; \
+ g = green; \
+}
+
+void keywordToRGB( QString rgbColor, int &r, int &g, int &b )
+{
+ if( rgbColor == "aliceblue" )
+ TORGB( 240, 248, 255)
+ else if( rgbColor == "antiquewhite" )
+ TORGB( 250, 235, 215)
+ else if( rgbColor == "aqua" )
+ TORGB( 0, 255, 255)
+ else if( rgbColor == "aquamarine" )
+ TORGB( 127, 255, 212 )
+ else if( rgbColor == "azure" )
+ TORGB( 240, 255, 255 )
+ else if( rgbColor == "beige" )
+ TORGB( 245, 245, 220 )
+ else if( rgbColor == "bisque" )
+ TORGB( 255, 228, 196 )
+ else if( rgbColor == "black" )
+ TORGB( 0, 0, 0 )
+ else if( rgbColor == "blanchedalmond" )
+ TORGB( 255, 235, 205 )
+ else if( rgbColor == "blue" )
+ TORGB( 0, 0, 255 )
+ else if( rgbColor == "blueviolet" )
+ TORGB( 138, 43, 226 )
+ else if( rgbColor == "brown" )
+ TORGB( 165, 42, 42 )
+ else if( rgbColor == "burlywood" )
+ TORGB( 222, 184, 135 )
+ else if( rgbColor == "cadetblue" )
+ TORGB( 95, 158, 160 )
+ else if( rgbColor == "chartreuse" )
+ TORGB( 127, 255, 0 )
+ else if( rgbColor == "chocolate" )
+ TORGB( 210, 105, 30 )
+ else if( rgbColor == "coral" )
+ TORGB( 255, 127, 80 )
+ else if( rgbColor == "cornflowerblue" )
+ TORGB( 100, 149, 237 )
+ else if( rgbColor == "cornsilk" )
+ TORGB( 255, 248, 220 )
+ else if( rgbColor == "crimson" )
+ TORGB( 220, 20, 60 )
+ else if( rgbColor == "cyan" )
+ TORGB( 0, 255, 255 )
+ else if( rgbColor == "darkblue" )
+ TORGB( 0, 0, 139 )
+ else if( rgbColor == "darkcyan" )
+ TORGB( 0, 139, 139 )
+ else if( rgbColor == "darkgoldenrod" )
+ TORGB( 184, 134, 11 )
+ else if( rgbColor == "darkgray" )
+ TORGB( 169, 169, 169 )
+ else if( rgbColor == "darkgrey" )
+ TORGB( 169, 169, 169 )
+ else if( rgbColor == "darkgreen" )
+ TORGB( 0, 100, 0 )
+ else if( rgbColor == "darkkhaki" )
+ TORGB( 189, 183, 107 )
+ else if( rgbColor == "darkmagenta" )
+ TORGB( 139, 0, 139 )
+ else if( rgbColor == "darkolivegreen" )
+ TORGB( 85, 107, 47 )
+ else if( rgbColor == "darkorange" )
+ TORGB( 255, 140, 0 )
+ else if( rgbColor == "darkorchid" )
+ TORGB( 153, 50, 204 )
+ else if( rgbColor == "darkred" )
+ TORGB( 139, 0, 0 )
+ else if( rgbColor == "darksalmon" )
+ TORGB( 233, 150, 122 )
+ else if( rgbColor == "darkseagreen" )
+ TORGB( 143, 188, 143 )
+ else if( rgbColor == "darkslateblue" )
+ TORGB( 72, 61, 139 )
+ else if( rgbColor == "darkslategray" )
+ TORGB( 47, 79, 79 )
+ else if( rgbColor == "darkslategrey" )
+ TORGB( 47, 79, 79 )
+ else if( rgbColor == "darkturquoise" )
+ TORGB( 0, 206, 209 )
+ else if( rgbColor == "darkviolet" )
+ TORGB( 148, 0, 211 )
+ else if( rgbColor == "deeppink" )
+ TORGB( 255, 20, 147 )
+ else if( rgbColor == "deepskyblue" )
+ TORGB( 0, 191, 255 )
+ else if( rgbColor == "dimgray" )
+ TORGB( 105, 105, 105 )
+ else if( rgbColor == "dimgrey" )
+ TORGB( 105, 105, 105 )
+ else if( rgbColor == "dodgerblue" )
+ TORGB( 30, 144, 255 )
+ else if( rgbColor == "firebrick" )
+ TORGB( 178, 34, 34 )
+ else if( rgbColor == "floralwhite" )
+ TORGB( 255, 250, 240 )
+ else if( rgbColor == "forestgreen" )
+ TORGB( 34, 139, 34 )
+ else if( rgbColor == "fuchsia" )
+ TORGB( 255, 0, 255 )
+ else if( rgbColor == "gainsboro" )
+ TORGB( 220, 220, 220 )
+ else if( rgbColor == "ghostwhite" )
+ TORGB( 248, 248, 255 )
+ else if( rgbColor == "gold" )
+ TORGB( 255, 215, 0 )
+ else if( rgbColor == "goldenrod" )
+ TORGB( 218, 165, 32 )
+ else if( rgbColor == "gray" )
+ TORGB( 128, 128, 128 )
+ else if( rgbColor == "grey" )
+ TORGB( 128, 128, 128 )
+ else if( rgbColor == "green" )
+ TORGB( 0, 128, 0 )
+ else if( rgbColor == "greenyellow" )
+ TORGB( 173, 255, 47 )
+ else if( rgbColor == "honeydew" )
+ TORGB( 240, 255, 240 )
+ else if( rgbColor == "hotpink" )
+ TORGB( 255, 105, 180 )
+ else if( rgbColor == "indianred" )
+ TORGB( 205, 92, 92 )
+ else if( rgbColor == "indigo" )
+ TORGB( 75, 0, 130 )
+ else if( rgbColor == "ivory" )
+ TORGB( 255, 255, 240 )
+ else if( rgbColor == "khaki" )
+ TORGB( 240, 230, 140 )
+ else if( rgbColor == "lavender" )
+ TORGB( 230, 230, 250 )
+ else if( rgbColor == "lavenderblush" )
+ TORGB( 255, 240, 245 )
+ else if( rgbColor == "lawngreen" )
+ TORGB( 124, 252, 0 )
+ else if( rgbColor == "lemonchiffon" )
+ TORGB( 255, 250, 205 )
+ else if( rgbColor == "lightblue" )
+ TORGB( 173, 216, 230 )
+ else if( rgbColor == "lightcoral" )
+ TORGB( 240, 128, 128 )
+ else if( rgbColor == "lightcyan" )
+ TORGB( 224, 255, 255 )
+ else if( rgbColor == "lightgoldenrodyellow" )
+ TORGB( 250, 250, 210 )
+ else if( rgbColor == "lightgray" )
+ TORGB( 211, 211, 211 )
+ else if( rgbColor == "lightgrey" )
+ TORGB( 211, 211, 211 )
+ else if( rgbColor == "lightgreen" )
+ TORGB( 144, 238, 144 )
+ else if( rgbColor == "lightpink" )
+ TORGB( 255, 182, 193 )
+ else if( rgbColor == "lightsalmon" )
+ TORGB( 255, 160, 122 )
+ else if( rgbColor == "lightseagreen" )
+ TORGB( 32, 178, 170 )
+ else if( rgbColor == "lightskyblue" )
+ TORGB( 135, 206, 250 )
+ else if( rgbColor == "lightslategray" )
+ TORGB( 119, 136, 153 )
+ else if( rgbColor == "lightslategrey" )
+ TORGB( 119, 136, 153 )
+ else if( rgbColor == "lightsteelblue" )
+ TORGB( 176, 196, 222 )
+ else if( rgbColor == "lightyellow" )
+ TORGB( 255, 255, 224 )
+ else if( rgbColor == "lime" )
+ TORGB( 0, 255, 0 )
+ else if( rgbColor == "limegreen" )
+ TORGB( 50, 205, 50 )
+ else if( rgbColor == "linen" )
+ TORGB( 250, 240, 230 )
+ else if( rgbColor == "magenta" )
+ TORGB( 255, 0, 255 )
+ else if( rgbColor == "maroon" )
+ TORGB( 128, 0, 0 )
+ else if( rgbColor == "mediumaquamarine" )
+ TORGB( 102, 205, 170 )
+ else if( rgbColor == "mediumblue" )
+ TORGB( 0, 0, 205 )
+ else if( rgbColor == "mediumorchid" )
+ TORGB( 186, 85, 211 )
+ else if( rgbColor == "mediumpurple" )
+ TORGB( 147, 112, 219 )
+ else if( rgbColor == "mediumseagreen" )
+ TORGB( 60, 179, 113 )
+ else if( rgbColor == "mediumslateblue" )
+ TORGB( 123, 104, 238 )
+ else if( rgbColor == "mediumspringgreen" )
+ TORGB( 0, 250, 154 )
+ else if( rgbColor == "mediumturquoise" )
+ TORGB( 72, 209, 204 )
+ else if( rgbColor == "mediumvioletred" )
+ TORGB( 199, 21, 133 )
+ else if( rgbColor == "midnightblue" )
+ TORGB( 25, 25, 112 )
+ else if( rgbColor == "mintcream" )
+ TORGB( 245, 255, 250 )
+ else if( rgbColor == "mistyrose" )
+ TORGB( 255, 228, 225 )
+ else if( rgbColor == "moccasin" )
+ TORGB( 255, 228, 181 )
+ else if( rgbColor == "navajowhite" )
+ TORGB( 255, 222, 173 )
+ else if( rgbColor == "navy" )
+ TORGB( 0, 0, 128 )
+ else if( rgbColor == "oldlace" )
+ TORGB( 253, 245, 230 )
+ else if( rgbColor == "olive" )
+ TORGB( 128, 128, 0 )
+ else if( rgbColor == "olivedrab" )
+ TORGB( 107, 142, 35 )
+ else if( rgbColor == "orange" )
+ TORGB( 255, 165, 0 )
+ else if( rgbColor == "orangered" )
+ TORGB( 255, 69, 0 )
+ else if( rgbColor == "orchid" )
+ TORGB( 218, 112, 214 )
+ else if( rgbColor == "palegoldenrod" )
+ TORGB( 238, 232, 170 )
+ else if( rgbColor == "palegreen" )
+ TORGB( 152, 251, 152 )
+ else if( rgbColor == "paleturquoise" )
+ TORGB( 175, 238, 238 )
+ else if( rgbColor == "palevioletred" )
+ TORGB( 219, 112, 147 )
+ else if( rgbColor == "papayawhip" )
+ TORGB( 255, 239, 213 )
+ else if( rgbColor == "peachpuff" )
+ TORGB( 255, 218, 185 )
+ else if( rgbColor == "peru" )
+ TORGB( 205, 133, 63 )
+ else if( rgbColor == "pink" )
+ TORGB( 255, 192, 203 )
+ else if( rgbColor == "plum" )
+ TORGB( 221, 160, 221 )
+ else if( rgbColor == "powderblue" )
+ TORGB( 176, 224, 230 )
+ else if( rgbColor == "purple" )
+ TORGB( 128, 0, 128 )
+ else if( rgbColor == "red" )
+ TORGB( 255, 0, 0 )
+ else if( rgbColor == "rosybrown" )
+ TORGB( 188, 143, 143 )
+ else if( rgbColor == "royalblue" )
+ TORGB( 65, 105, 225 )
+ else if( rgbColor == "saddlebrown" )
+ TORGB( 139, 69, 19 )
+ else if( rgbColor == "salmon" )
+ TORGB( 250, 128, 114 )
+ else if( rgbColor == "sandybrown" )
+ TORGB( 244, 164, 96 )
+ else if( rgbColor == "seagreen" )
+ TORGB( 46, 139, 87 )
+ else if( rgbColor == "seashell" )
+ TORGB( 255, 245, 238 )
+ else if( rgbColor == "sienna" )
+ TORGB( 160, 82, 45 )
+ else if( rgbColor == "silver" )
+ TORGB( 192, 192, 192 )
+ else if( rgbColor == "skyblue" )
+ TORGB( 135, 206, 235 )
+ else if( rgbColor == "slateblue" )
+ TORGB( 106, 90, 205 )
+ else if( rgbColor == "slategray" )
+ TORGB( 112, 128, 144 )
+ else if( rgbColor == "slategrey" )
+ TORGB( 112, 128, 144 )
+ else if( rgbColor == "snow" )
+ TORGB( 255, 250, 250 )
+ else if( rgbColor == "springgreen" )
+ TORGB( 0, 255, 127 )
+ else if( rgbColor == "steelblue" )
+ TORGB( 70, 130, 180 )
+ else if( rgbColor == "tan" )
+ TORGB( 210, 180, 140 )
+ else if( rgbColor == "teal" )
+ TORGB( 0, 128, 128 )
+ else if( rgbColor == "thistle" )
+ TORGB( 216, 191, 216 )
+ else if( rgbColor == "tomato" )
+ TORGB( 255, 99, 71 )
+ else if( rgbColor == "turquoise" )
+ TORGB( 64, 224, 208 )
+ else if( rgbColor == "violet" )
+ TORGB( 238, 130, 238 )
+ else if( rgbColor == "wheat" )
+ TORGB( 245, 222, 179 )
+ else if( rgbColor == "white" )
+ TORGB( 255, 255, 255 )
+ else if( rgbColor == "whitesmoke" )
+ TORGB( 245, 245, 245 )
+ else if( rgbColor == "yellow" )
+ TORGB( 255, 255, 0 )
+ else if( rgbColor == "yellowgreen" )
+ TORGB( 154, 205, 50 )
+}
+
diff --git a/filters/karbon/svg/karbon_svg_export.desktop b/filters/karbon/svg/karbon_svg_export.desktop
new file mode 100644
index 00000000..e0990478
--- /dev/null
+++ b/filters/karbon/svg/karbon_svg_export.desktop
@@ -0,0 +1,67 @@
+[Desktop Entry]
+Icon=
+Name=Karbon14 SVG Export Filter
+Name[af]=Karbon14 Svg Voer uit Filter
+Name[ar]=مِرْشَح تصدير SVG لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в SVG
+Name[br]=Sil ezporzh SVG evit Karbon14
+Name[ca]=Filtre d'exportació SVG per a Karbon14
+Name[cs]=Exportní filtr do formátu SVG pro Karbon14
+Name[cy]=Hidlen Allforio SVG Karbon14
+Name[da]=Karbon14 SVG-eksportfilter
+Name[de]=Karbon14 SVG-Exportfilter
+Name[el]=Φίλτρο εξαγωγής SVG του Karbon14
+Name[eo]=Karbon-SVG-eksportfiltrilo
+Name[es]=Filtro de exportación Karbon14 SVG
+Name[et]=Karbon14 SVG ekspordifilter
+Name[eu]=Karbon14-en SVG esportaziorako iragazkia
+Name[fa]=پالایۀ صادرات Karbon14 SVG
+Name[fi]=Karbon14 SVG -vientisuodin
+Name[fr]=Filtre d'exportation SVG de Karbon 14
+Name[fy]=SVG-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála SVG Karbon14
+Name[gl]=Filtro de Exportación de SVG para Karbon14
+Name[he]=מסנן ייצוא מ־Karbon14 ל־SVG
+Name[hr]=Karbon14 SVG filtar izvoza
+Name[hu]=Karbon14 SVG exportszűrő
+Name[is]=Karbon14 SVG útflutningssía
+Name[it]=Filtro di esportazione SVG per Karbon14
+Name[ja]=Karbon14 SVG エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ SVG សម្រាប់ Karbon14
+Name[lo]= ຕົວຕອງການສົ່ງອອກ SVG ຂອງ Karbon14
+Name[lt]=Karbon14 SVG eksportavimo filtras
+Name[lv]=Karbon14 SVG eksporta filtrs
+Name[ms]=Penapis Eksport Karbon14 SVG
+Name[mt]=Filtru għall-esportazzjoni ta' SVG minn ġo Karbon14
+Name[nb]=SVG-eksportfiler for Karbon14
+Name[nds]=SVG-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ एसभीजी निर्यात फिल्टर
+Name[nl]=SVG-exportfilter voor Karbon14
+Name[nn]=SVG-eksportfilter for Karbon14
+Name[pl]=Filtr eksportu do formatu SVG z Karbon14
+Name[pt]=Filtro de Exportação de SVG para o Karbon14
+Name[pt_BR]=Filtro de Exportação SVG do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru SVG
+Name[ru]=Фильтр экспорта рисунков Karbon в SVG
+Name[se]=Karbon14:a SVG-olggosfievrridansilli
+Name[sk]=SVG filter pre export z Karbon14
+Name[sl]=Izvozni filter SVG za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у SVG
+Name[sr@Latn]=Karbon14-ov filter za izvoz u SVG
+Name[sv]=Karbon14 SVG-exportfilter
+Name[ta]=Karbon 14 SVG ஏற்றுமதி வடிகட்டி
+Name[tg]=Karbon14 SVG Филтри Содирот
+Name[th]=ตัวกรองการส่งออก SVG ของ Karbon14
+Name[tr]=Karbon14 SVG Aktarma Filtresi
+Name[uk]=Фільтр експорту SVG для Karbon14
+Name[uz]=Karbon14 SVG eksport filteri
+Name[uz@cyrillic]=Karbon14 SVG экспорт филтери
+Name[xh]=Isihluzi Sokurhweba Sangaphandle se Karbon14 SVG
+Name[zh_CN]=Karbon14 SVG 导出过滤器
+Name[zh_TW]=Karbon14 SVG 匯出過濾程式
+ServiceTypes=KOfficeFilter
+Type=Service
+X-KDE-Export=image/svg+xml
+X-KDE-Import=application/x-karbon
+X-KDE-Library=libkarbonsvgexport
+X-KDE-Weight=1
diff --git a/filters/karbon/svg/karbon_svg_import.desktop b/filters/karbon/svg/karbon_svg_import.desktop
new file mode 100644
index 00000000..a1f7eaea
--- /dev/null
+++ b/filters/karbon/svg/karbon_svg_import.desktop
@@ -0,0 +1,64 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon SVG Import Filter
+Name[af]=Karbon Svg In voer Filter
+Name[ar]=مِرْشَح استيراد SVG لدى Karbon
+Name[bg]=Филтър за импортиране от SVG в Karbon
+Name[br]=Sil enporzh SVG evit Karbon
+Name[ca]=Filtre d'importació SVG per a Karbon
+Name[cs]=Exportní filtr do formátu SVG pro Karbon
+Name[cy]=Hidlen Fewnforio SVG Karbon
+Name[da]=Karbon SVG-importfilter
+Name[de]=Karbon14 SVG-Importfilter
+Name[el]=Φίλτρο εισαγωγής SVG του Karbon
+Name[eo]=Karbon-SVG-importfiltrilo
+Name[es]=Filtro de importación de SVG de Karbon
+Name[et]=Karboni SVG impordifilter
+Name[eu]=Karbon-en SVG inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon SVG
+Name[fi]=Karbon SVG -tuontisuodin
+Name[fr]=Filtre d'exportation SVG de Karbon 14
+Name[fy]=SVG-Ymportfilter foar Karbon
+Name[ga]=Scagaire Iompórtála Karbon SVG
+Name[gl]=Filtro de Importación de SVG para Karbon
+Name[he]=מסנן ייבוא מ־SVG ל־Karbon
+Name[hr]=Karbon SVG filtar uvoza
+Name[hu]=Karbon SVG importszűrő
+Name[is]=Karbon SVG innflutningssía
+Name[it]=Filtro di importazione SVG per Karbon14
+Name[ja]=Karbon SVG インポートフィルタ
+Name[km]=តម្រង​នាំចូល SVG សម្រាប់ Karbon
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ EPS ຂອງຄາຮ໌ບອນ14
+Name[lt]=Karbon SVG importavimo filtras
+Name[lv]=Karbon SVG importa filtrs
+Name[ms]=Penapis Import Karbon SVG
+Name[nb]=SVG-importfilter for Karbon
+Name[nds]=SVG-Importfilter för Karbon
+Name[ne]=कार्बन एसभीजी निर्यात फिल्टर
+Name[nl]=SVG-importfilter voor Karbon14
+Name[nn]=SVG-importfilter for Karbon
+Name[pl]=Filtr importu formatu SVG do Karbon
+Name[pt]=Filtro de Importação de SVG para o Karbon
+Name[pt_BR]=Filtro de Importação SVG do Karbon
+Name[ro]=Filtru importare Karbon14 pentru SVG
+Name[ru]=Фильтр импорта рисунков SVG в Karbon
+Name[se]=Karbon:a SVG-sisafievrridansilli
+Name[sk]=SVG filter pre import do Karbon
+Name[sl]=Uvozni filter SVG za Karbon
+Name[sr]=Karbon-ов филтер за увоз из SVG-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz SVG-a
+Name[sv]=Karbon SVG-importfilter
+Name[ta]=Karbon SVG ஏற்றுமதி வடிகட்டி
+Name[tg]=Karbon SVG I Филтри Воридот
+Name[tr]=Karbon SVG Alma Filtresi
+Name[uk]=Фільтр імпорту малюнків SVG у Karbon
+Name[uz]=Karbon SVG import filteri
+Name[uz@cyrillic]=Karbon SVG импорт филтери
+Name[xh]=Isihluzi Sokurhweba se Karbon SVG
+Name[zh_CN]=Karbon SVG 导入过滤器
+Name[zh_TW]=Karbon SVG 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=image/svg+xml
+X-KDE-Weight=1
+X-KDE-Library=libkarbonsvgimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/svg/svgexport.cc b/filters/karbon/svg/svgexport.cc
new file mode 100644
index 00000000..4f434d4d
--- /dev/null
+++ b/filters/karbon/svg/svgexport.cc
@@ -0,0 +1,512 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcstring.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kgenericfactory.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include "svgexport.h"
+#include "vcolor.h"
+#include "vcomposite.h"
+#include "vdashpattern.h"
+#include "vdocument.h"
+#include "vfill.h"
+#include "vgradient.h"
+#include "vgroup.h"
+#include "vimage.h"
+#include "vlayer.h"
+#include "vpath.h"
+#include "vpattern.h"
+#include "vsegment.h"
+#include "vselection.h"
+#include "vstroke.h"
+#include "vtext.h"
+#include <commands/vtransformcmd.h>
+
+#include <kdebug.h>
+
+QString INDENT(" ");
+
+void
+printIndentation( QTextStream *stream, unsigned int indent )
+{
+ for( unsigned int i = 0; i < indent;++i)
+ *stream << INDENT;
+}
+
+typedef KGenericFactory<SvgExport, KoFilter> SvgExportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonsvgexport, SvgExportFactory( "kofficefilters" ) )
+
+
+SvgExport::SvgExport( KoFilter*, const char*, const QStringList& )
+ : KoFilter(), m_indent( 0 ), m_indent2( 0 ), m_trans( 0L )
+{
+ m_gc.setAutoDelete( true );
+}
+
+KoFilter::ConversionStatus
+SvgExport::convert( const QCString& from, const QCString& to )
+{
+ if ( to != "image/svg+xml" || from != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+ if( !storeIn )
+ return KoFilter::StupidError;
+
+ QFile fileOut( m_chain->outputFile() );
+ if( !fileOut.open( IO_WriteOnly ) )
+ {
+ delete storeIn;
+ return KoFilter::StupidError;
+ }
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ m_stream = new QTextStream( &fileOut );
+ QString body;
+ m_body = new QTextStream( &body, IO_ReadWrite );
+ QString defs;
+ m_defs = new QTextStream( &defs, IO_ReadWrite );
+
+ // load the document and export it:
+ VDocument doc;
+ doc.load( docNode );
+ doc.accept( *this );
+
+ *m_stream << defs;
+ *m_stream << body;
+
+ fileOut.close();
+
+ delete m_stream;
+ delete m_defs;
+ delete m_body;
+
+ return KoFilter::OK;
+}
+
+void
+SvgExport::visitVDocument( VDocument& document )
+{
+ // select all objects:
+ document.selection()->append();
+
+ // get the bounding box of the page
+ KoRect rect( 0, 0, document.width(), document.height() );
+
+ // standard header:
+ *m_defs <<
+ "<?xml version=\"1.0\" standalone=\"no\"?>\n" <<
+ "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" " <<
+ "\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">"
+ << endl;
+
+ // add some PR. one line is more than enough.
+ *m_defs <<
+ "<!-- Created using Karbon14, part of koffice: http://www.koffice.org/karbon -->" << endl;
+
+ *m_defs <<
+ "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"" <<
+ rect.width() << "px\" height=\"" << rect.height() << "px\">" << endl;
+ printIndentation( m_defs, ++m_indent2 );
+ *m_defs << "<defs>" << endl;
+
+ m_indent++;
+ m_indent2++;
+
+ // we dont need the selection anymore:
+ document.selection()->clear();
+
+ // set up gc
+ SvgGraphicsContext *gc = new SvgGraphicsContext;
+ m_gc.push( gc );
+
+ QWMatrix mat;
+ mat.scale( 1, -1 );
+ mat.translate( 0, -document.height() );
+
+ m_trans = new VTransformCmd( 0L, mat, false );
+
+ // export layers:
+ VVisitor::visitVDocument( document );
+
+ delete m_trans;
+ m_trans = 0L;
+
+ // end tag:
+ printIndentation( m_defs, --m_indent2 );
+ *m_defs << "</defs>" << endl;
+ *m_body << "</svg>" << endl;
+}
+
+QString
+SvgExport::getID( VObject *obj )
+{
+ if( obj && !obj->name().isEmpty() )
+ return QString( " id=\"%1\"" ).arg( obj->name() );
+ return QString();
+}
+
+void
+SvgExport::visitVGroup( VGroup& group )
+{
+ printIndentation( m_body, m_indent++ );
+ *m_body << "<g" << getID( &group ) << ">" << endl;
+ VVisitor::visitVGroup( group );
+ printIndentation( m_body, --m_indent );
+ *m_body << "</g>" << endl;
+}
+
+// horrible but at least something gets exported now
+// will need this for patterns
+void
+SvgExport::visitVImage( VImage& image )
+{
+ printIndentation( m_body, m_indent );
+ *m_body << "<image ";
+ VVisitor::visitVImage( image );
+ *m_body << "x=\"" << "\" ";
+ *m_body << "y=\"" << "\" ";
+ *m_body << "width=\"" << "\" ";
+ *m_body << "height=\"" << "\" ";
+ *m_body << "xlink:href=\"" << "\"";
+ *m_body << " />" << endl;
+}
+
+void
+SvgExport::visitVLayer( VLayer& layer )
+{
+ printIndentation( m_body, m_indent++ );
+ *m_body << "<g" << getID( &layer ) << ">" << endl;
+ //*m_body << " transform=\"scale(1, -1) translate(0, -" << layer.document()->height() << ")\">" << endl;
+ VVisitor::visitVLayer( layer );
+ printIndentation( m_body, --m_indent );
+ *m_body << "</g>" << endl;
+}
+
+void
+SvgExport::writePathToStream( VPath &composite, const QString &id, QTextStream *stream, unsigned int indent )
+{
+ if( ! stream )
+ return;
+
+ printIndentation( stream, indent );
+ *stream << "<path" << id;
+
+ VVisitor::visitVPath( composite );
+
+ getFill( *( composite.fill() ), stream );
+ getStroke( *( composite.stroke() ), stream );
+
+ QString d;
+ composite.saveSvgPath( d );
+ *stream << " d=\"" << d << "\" ";
+
+ if( composite.fillRule() != m_gc.current()->fillRule )
+ {
+ if( composite.fillRule() == evenOdd )
+ *stream << " fill-rule=\"evenodd\"";
+ else
+ *stream << " fill-rule=\"nonzero\"";
+ }
+
+ *stream << " />" << endl;
+}
+
+void
+SvgExport::visitVPath( VPath& composite )
+{
+ m_trans->visitVPath( composite );
+ writePathToStream( composite, getID( &composite ), m_body, m_indent );
+ m_trans->visitVPath( composite );
+}
+
+void
+SvgExport::visitVSubpath( VSubpath& )
+{
+}
+
+QString createUID()
+{
+ static unsigned int nr = 0;
+
+ return "defitem" + QString().setNum( nr++ );
+}
+
+void
+SvgExport::getColorStops( const QPtrVector<VColorStop> &colorStops )
+{
+ m_indent2++;
+ for( unsigned int i = 0; i < colorStops.count() ; i++ )
+ {
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "<stop stop-color=\"";
+ getHexColor( m_defs, colorStops.at( i )->color );
+ *m_defs << "\" offset=\"" << QString().setNum( colorStops.at( i )->rampPoint );
+ *m_defs << "\" stop-opacity=\"" << colorStops.at( i )->color.opacity() << "\"" << " />" << endl;
+ }
+ m_indent2--;
+}
+
+void
+SvgExport::getGradient( const VGradient& grad )
+{
+ QString uid = createUID();
+ if( grad.type() == VGradient::linear )
+ {
+ printIndentation( m_defs, m_indent2 );
+ // do linear grad
+ *m_defs << "<linearGradient id=\"" << uid << "\" ";
+ *m_defs << "gradientUnits=\"userSpaceOnUse\" ";
+ *m_defs << "x1=\"" << grad.origin().x() << "\" ";
+ *m_defs << "y1=\"" << grad.origin().y() << "\" ";
+ *m_defs << "x2=\"" << grad.vector().x() << "\" ";
+ *m_defs << "y2=\"" << grad.vector().y() << "\" ";
+ if( grad.repeatMethod() == VGradient::reflect )
+ *m_defs << "spreadMethod=\"reflect\" ";
+ else if( grad.repeatMethod() == VGradient::repeat )
+ *m_defs << "spreadMethod=\"repeat\" ";
+ *m_defs << ">" << endl;
+
+ // color stops
+ getColorStops( grad.colorStops() );
+
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "</linearGradient>" << endl;
+ *m_body << "url(#" << uid << ")";
+ }
+ else if( grad.type() == VGradient::radial )
+ {
+ // do radial grad
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "<radialGradient id=\"" << uid << "\" ";
+ *m_defs << "gradientUnits=\"userSpaceOnUse\" ";
+ *m_defs << "cx=\"" << grad.origin().x() << "\" ";
+ *m_defs << "cy=\"" << grad.origin().y() << "\" ";
+ *m_defs << "fx=\"" << grad.focalPoint().x() << "\" ";
+ *m_defs << "fy=\"" << grad.focalPoint().y() << "\" ";
+ double r = sqrt( pow( grad.vector().x() - grad.origin().x(), 2 ) + pow( grad.vector().y() - grad.origin().y(), 2 ) );
+ *m_defs << "r=\"" << QString().setNum( r ) << "\" ";
+ if( grad.repeatMethod() == VGradient::reflect )
+ *m_defs << "spreadMethod=\"reflect\" ";
+ else if( grad.repeatMethod() == VGradient::repeat )
+ *m_defs << "spreadMethod=\"repeat\" ";
+ *m_defs << ">" << endl;
+
+ // color stops
+ getColorStops( grad.colorStops() );
+
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "</radialGradient>" << endl;
+ *m_body << "url(#" << uid << ")";
+ }
+ // gah! pointless abbreviation of conical to conic
+ else if( grad.type() == VGradient::conic )
+ {
+ // fake conical grad as radial.
+ // fugly but better than data loss.
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "<radialGradient id=\"" << uid << "\" ";
+ *m_defs << "gradientUnits=\"userSpaceOnUse\" ";
+ *m_defs << "cx=\"" << grad.origin().x() << "\" ";
+ *m_defs << "cy=\"" << grad.origin().y() << "\" ";
+ *m_defs << "fx=\"" << grad.focalPoint().x() << "\" ";
+ *m_defs << "fy=\"" << grad.focalPoint().y() << "\" ";
+ double r = sqrt( pow( grad.vector().x() - grad.origin().x(), 2 ) + pow( grad.vector().y() - grad.origin().y(), 2 ) );
+ *m_defs << "r=\"" << QString().setNum( r ) << "\" ";
+ if( grad.repeatMethod() == VGradient::reflect )
+ *m_defs << "spreadMethod=\"reflect\" ";
+ else if( grad.repeatMethod() == VGradient::repeat )
+ *m_defs << "spreadMethod=\"repeat\" ";
+ *m_defs << ">" << endl;
+
+ // color stops
+ getColorStops( grad.colorStops() );
+
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "</radialGradient>" << endl;
+ *m_body << "url(#" << uid << ")";
+ }
+}
+
+// better than nothing
+void
+SvgExport::getPattern( const VPattern & )
+{
+ QString uid = createUID();
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "<pattern id=\"" << uid << "\" ";
+ *m_defs << "width=\"" << "\" ";
+ *m_defs << "height=\"" << "\" ";
+ *m_defs << "patternUnits=\"userSpaceOnUse\" ";
+ *m_defs << "patternContentUnits=\"userSpaceOnUse\" ";
+ *m_defs << " />" << endl;
+ // TODO: insert hard work here ;)
+ printIndentation( m_defs, m_indent2 );
+ *m_defs << "</pattern>" << endl;
+ *m_body << "url(#" << uid << ")";
+}
+
+void
+SvgExport::getFill( const VFill& fill, QTextStream *stream )
+{
+ *stream << " fill=\"";
+ if( fill.type() == VFill::none )
+ *stream << "none";
+ else if( fill.type() == VFill::grad )
+ getGradient( fill.gradient() );
+ else if( fill.type() == VFill::patt )
+ getPattern( fill.pattern() );
+ else
+ getHexColor( stream, fill.color() );
+ *stream << "\"";
+
+ if( fill.color().opacity() != m_gc.current()->fill.color().opacity() )
+ *stream << " fill-opacity=\"" << fill.color().opacity() << "\"";
+}
+
+void
+SvgExport::getStroke( const VStroke& stroke, QTextStream *stream )
+{
+ if( stroke.type() != m_gc.current()->stroke.type() )
+ {
+ *stream << " stroke=\"";
+ if( stroke.type() == VStroke::none )
+ *stream << "none";
+ else if( stroke.type() == VStroke::grad )
+ getGradient( stroke.gradient() );
+ else
+ getHexColor( stream, stroke.color() );
+ *stream << "\"";
+ }
+
+ if( stroke.color().opacity() != m_gc.current()->stroke.color().opacity() )
+ *stream << " stroke-opacity=\"" << stroke.color().opacity() << "\"";
+
+ if( stroke.lineWidth() != m_gc.current()->stroke.lineWidth() )
+ *stream << " stroke-width=\"" << stroke.lineWidth() << "\"";
+
+ if( stroke.lineCap() != m_gc.current()->stroke.lineCap() )
+ {
+ if( stroke.lineCap() == VStroke::capButt )
+ *stream << " stroke-linecap=\"butt\"";
+ else if( stroke.lineCap() == VStroke::capRound )
+ *stream << " stroke-linecap=\"round\"";
+ else if( stroke.lineCap() == VStroke::capSquare )
+ *stream << " stroke-linecap=\"square\"";
+ }
+
+ if( stroke.lineJoin() != m_gc.current()->stroke.lineJoin() )
+ {
+ if( stroke.lineJoin() == VStroke::joinMiter )
+ {
+ *stream << " stroke-linejoin=\"miter\"";
+ *stream << " stroke-miterlimit=\"" << stroke.miterLimit() << "\"";
+ }
+ else if( stroke.lineJoin() == VStroke::joinRound )
+ *stream << " stroke-linejoin=\"round\"";
+ else if( stroke.lineJoin() == VStroke::joinBevel )
+ *stream << " stroke-linejoin=\"bevel\"";
+ }
+
+ // dash
+ if( stroke.dashPattern().array().count() > 0 )
+ {
+ *stream << " stroke-dashoffset=\"" << stroke.dashPattern().offset() << "\"";
+ *stream << " stroke-dasharray=\" ";
+
+ QValueListConstIterator<float> itr;
+ for(itr = stroke.dashPattern().array().begin(); itr != stroke.dashPattern().array().end(); ++itr )
+ {
+ *stream << *itr << " ";
+ }
+ *stream << "\"";
+ }
+}
+
+void
+SvgExport::getHexColor( QTextStream *stream, const VColor& color )
+{
+ // Convert the various color-spaces to hex
+
+ QString Output;
+
+ VColor copy( color );
+ copy.setColorSpace( VColor::rgb );
+
+ Output.sprintf( "#%02x%02x%02x", int( copy[0] * 255.0 ), int( copy[1] * 255.0 ), int( copy[2] * 255.0 ) );
+
+ *stream << Output;
+}
+
+void
+SvgExport::visitVText( VText& text )
+{
+ VPath path( 0L );
+ path.combinePath( text.basePath() );
+
+ m_trans->visitVPath( path );
+
+ QString id = createUID();
+ writePathToStream( path, " id=\""+ id + "\"", m_defs, m_indent2 );
+
+ printIndentation( m_body, m_indent++ );
+ *m_body << "<text" << getID( &text );
+ //*m_body << " transform=\"scale(1, -1) translate(0, -" << text.document()->height() << ")\"";
+ getFill( *( text.fill() ), m_body );
+ getStroke( *( text.stroke() ), m_body );
+
+ *m_body << " font-family=\"" << text.font().family() << "\"";
+ *m_body << " font-size=\"" << text.font().pointSize() << "\"";
+ if( text.font().bold() )
+ *m_body << " font-weight=\"bold\"";
+ if( text.font().italic() )
+ *m_body << " font-style=\"italic\"";
+ if( text.alignment() == VText::Center )
+ *m_body << " text-anchor=\"middle\"";
+ else if( text.alignment() == VText::Right )
+ *m_body << " text-anchor=\"end\"";
+
+ *m_body << ">" << endl;
+
+ printIndentation( m_body, m_indent );
+ *m_body << "<textPath xlink:href=\"#" << id << "\"";
+ if( text.offset() > 0.0 )
+ *m_body << " startOffset=\"" << text.offset() * 100.0 << "%\"";
+ *m_body << ">";
+ *m_body << text.text();
+ *m_body << "</textPath>" << endl;
+ printIndentation( m_body, --m_indent );
+ *m_body << "</text>" << endl;
+}
+
+#include "svgexport.moc"
+
diff --git a/filters/karbon/svg/svgexport.h b/filters/karbon/svg/svgexport.h
new file mode 100644
index 00000000..8a4eab63
--- /dev/null
+++ b/filters/karbon/svg/svgexport.h
@@ -0,0 +1,88 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __SVGEXPORT_H__
+#define __SVGEXPORT_H__
+
+#include <KoFilter.h>
+
+#include "vvisitor.h"
+#include "vgradient.h"
+
+#include "svggraphiccontext.h"
+
+#include <qptrstack.h>
+
+class QTextStream;
+class VColor;
+class VPath;
+class VDocument;
+class VFill;
+class VGroup;
+class VImage;
+class VLayer;
+class VSubpath;
+class VStroke;
+class VText;
+class VTransformCmd;
+
+
+class SvgExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ SvgExport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~SvgExport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+private:
+ virtual void visitVPath( VPath& composite );
+ virtual void visitVDocument( VDocument& document );
+ virtual void visitVGroup( VGroup& group );
+ virtual void visitVImage( VImage& image );
+ virtual void visitVLayer( VLayer& layer );
+ virtual void visitVSubpath( VSubpath& path );
+ virtual void visitVText( VText& text );
+
+ void getStroke( const VStroke& stroke, QTextStream *stream );
+ void getColorStops( const QPtrVector<VColorStop> &colorStops );
+ void getFill( const VFill& fill, QTextStream *stream );
+ void getGradient( const VGradient& grad );
+ void getPattern( const VPattern& patt );
+ void getHexColor( QTextStream *, const VColor& color );
+ QString getID( VObject *obj );
+
+ void writePathToStream( VPath &composite, const QString &id, QTextStream *stream, unsigned int indent );
+
+ QTextStream* m_stream;
+ QTextStream* m_defs;
+ QTextStream* m_body;
+
+ QPtrStack<SvgGraphicsContext> m_gc;
+
+ unsigned int m_indent;
+ unsigned int m_indent2;
+
+ VTransformCmd *m_trans;
+};
+
+#endif
+
diff --git a/filters/karbon/svg/svggraphiccontext.h b/filters/karbon/svg/svggraphiccontext.h
new file mode 100644
index 00000000..96737fd9
--- /dev/null
+++ b/filters/karbon/svg/svggraphiccontext.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __SVGGRAPHICSCONTEXT_H__
+#define __SVGGRAPHICSCONTEXT_H__
+
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vfillrule.h>
+
+class SvgGraphicsContext
+{
+public:
+ SvgGraphicsContext()
+ {
+ stroke.setType( VStroke::none ); // default is no stroke
+ stroke.setLineWidth( 1.0 );
+ stroke.setLineCap( VStroke::capButt );
+ stroke.setLineJoin( VStroke::joinMiter );
+ fill.setColor( VColor( Qt::black ) );
+ fillRule = winding;
+ color = Qt::black;
+ }
+ VFill fill;
+ VFillRule fillRule;
+ VStroke stroke;
+ QWMatrix matrix;
+ QFont font;
+ QColor color;
+};
+
+#endif
diff --git a/filters/karbon/svg/svgimport.cc b/filters/karbon/svg/svgimport.cc
new file mode 100644
index 00000000..f97546c6
--- /dev/null
+++ b/filters/karbon/svg/svgimport.cc
@@ -0,0 +1,1389 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <svgimport.h>
+#include "color.h"
+#include <KoFilterChain.h>
+#include <KoPageLayout.h>
+#include <kgenericfactory.h>
+#include <kdebug.h>
+#include <KoUnit.h>
+#include <KoGlobal.h>
+#include <shapes/vellipse.h>
+#include <shapes/vrectangle.h>
+#include <shapes/vpolygon.h>
+#include <commands/vtransformcmd.h>
+#include <core/vsegment.h>
+#include <core/vtext.h>
+#include <core/vglobal.h>
+#include <core/vgroup.h>
+#include <core/vimage.h>
+#include <core/vlayer.h>
+#include <qcolor.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include <kfilterdev.h>
+
+typedef KGenericFactory<SvgImport, KoFilter> SvgImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonsvgimport, SvgImportFactory( "kofficefilters" ) )
+
+SvgImport::SvgImport(KoFilter *, const char *, const QStringList&) :
+ KoFilter(),
+ outdoc( "DOC" )
+{
+ m_gc.setAutoDelete( true );
+}
+
+SvgImport::~SvgImport()
+{
+}
+
+KoFilter::ConversionStatus SvgImport::convert(const QCString& from, const QCString& to)
+{
+ // check for proper conversion
+ if( to != "application/x-karbon" || from != "image/svg+xml" )
+ return KoFilter::NotImplemented;
+
+ //Find the last extension
+ QString strExt;
+ QString fileIn ( m_chain->inputFile() );
+ const int result=fileIn.findRev('.');
+ if (result>=0)
+ strExt=fileIn.mid(result).lower();
+
+ QString strMime; // Mime type of the compressor
+ if ((strExt==".gz") //in case of .svg.gz (logical extension)
+ ||(strExt==".svgz")) //in case of .svgz (extension used prioritary)
+ strMime="application/x-gzip"; // Compressed with gzip
+ else if (strExt==".bz2") //in case of .svg.bz2 (logical extension)
+ strMime="application/x-bzip2"; // Compressed with bzip2
+ else
+ strMime="text/plain";
+
+ /*kdDebug(30514) << "File extension: -" << strExt << "- Compression: " << strMime << endl;*/
+
+ QIODevice* in = KFilterDev::deviceForFile(fileIn,strMime);
+
+ if (!in->open(IO_ReadOnly))
+ {
+ kdError(30514) << "Cannot open file! Aborting!" << endl;
+ delete in;
+ return KoFilter::FileNotFound;
+ }
+
+ int line, col;
+ QString errormessage;
+
+ const bool parsed=inpdoc.setContent( in, &errormessage, &line, &col );
+
+ in->close();
+ delete in;
+
+ if ( ! parsed )
+ {
+ kdError(30514) << "Error while parsing file: "
+ << "at line " << line << " column: " << col
+ << " message: " << errormessage << endl;
+ // ### TODO: feedback to the user
+ return KoFilter::ParsingError;
+ }
+
+ // Do the conversion!
+ convert();
+ // add paper info, we always need custom for svg (Rob)
+ QDomElement paper = outdoc.createElement( "PAPER" );
+ outdoc.documentElement().appendChild( paper );
+ paper.setAttribute( "format", PG_CUSTOM );
+ paper.setAttribute( "width", m_document.width() );
+ paper.setAttribute( "height", m_document.height() );
+
+ KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
+ if( !out )
+ {
+ kdError(30514) << "Unable to open output file!" << endl;
+ return KoFilter::StorageCreationError;
+ }
+ QCString cstring = outdoc.toCString(); // utf-8 already
+ out->writeBlock( cstring.data(), cstring.length() );
+
+ return KoFilter::OK; // was successful
+}
+
+void SvgImport::convert()
+{
+ SvgGraphicsContext *gc = new SvgGraphicsContext;
+ QDomElement docElem = inpdoc.documentElement();
+ KoRect bbox( 0, 0, 550.0, 841.0 );
+ double width = !docElem.attribute( "width" ).isEmpty() ? parseUnit( docElem.attribute( "width" ), true, false, bbox ) : 550.0;
+ double height = !docElem.attribute( "height" ).isEmpty() ? parseUnit( docElem.attribute( "height" ), false, true, bbox ) : 841.0;
+ m_document.setWidth( width );
+ m_document.setHeight( height );
+
+ m_outerRect = m_document.boundingBox();
+
+ // undo y-mirroring
+ //m_debug->append(QString("%1\tUndo Y-mirroring.").arg(m_time.elapsed()));
+ if( !docElem.attribute( "viewBox" ).isEmpty() )
+ {
+ // allow for viewbox def with ',' or whitespace
+ QString viewbox( docElem.attribute( "viewBox" ) );
+ QStringList points = QStringList::split( ' ', viewbox.replace( ',', ' ').simplifyWhiteSpace() );
+
+ gc->matrix.scale( width / points[2].toFloat() , height / points[3].toFloat() );
+ m_outerRect.setWidth( m_outerRect.width() * ( points[2].toFloat() / width ) );
+ m_outerRect.setHeight( m_outerRect.height() * ( points[3].toFloat() / height ) );
+ }
+
+ m_gc.push( gc );
+ parseGroup( 0L, docElem );
+
+ QWMatrix mat;
+ mat.scale( 1, -1 );
+ mat.translate( 0, -m_document.height() );
+ VTransformCmd trafo( 0L, mat );
+ trafo.visit( m_document );
+ outdoc = m_document.saveXML();
+}
+
+#define DPI 90
+
+// Helper functions
+// ---------------------------------------------------------------------------------------
+
+double SvgImport::toPercentage( QString s )
+{
+ if( s.endsWith( "%" ) )
+ return s.remove( '%' ).toDouble();
+ else
+ return s.toDouble() * 100.0;
+}
+
+double SvgImport::fromPercentage( QString s )
+{
+ if( s.endsWith( "%" ) )
+ return s.remove( '%' ).toDouble() / 100.0;
+ else
+ return s.toDouble();
+}
+
+double SvgImport::getScalingFromMatrix( QWMatrix &matrix )
+{
+ double xscale = matrix.m11() + matrix.m12();
+ double yscale = matrix.m22() + matrix.m21();
+ return sqrt( xscale*xscale + yscale*yscale ) / sqrt( 2.0 );
+}
+
+// parses the number into parameter number
+const char * getNumber( const char *ptr, double &number )
+{
+ int integer, exponent;
+ double decimal, frac;
+ int sign, expsign;
+
+ exponent = 0;
+ integer = 0;
+ frac = 1.0;
+ decimal = 0;
+ sign = 1;
+ expsign = 1;
+
+ // read the sign
+ if(*ptr == '+')
+ ptr++;
+ else if(*ptr == '-')
+ {
+ ptr++;
+ sign = -1;
+ }
+
+ // read the integer part
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ integer = (integer * 10) + *(ptr++) - '0';
+ if(*ptr == '.') // read the decimals
+ {
+ ptr++;
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ decimal += (*(ptr++) - '0') * (frac *= 0.1);
+ }
+
+ if(*ptr == 'e' || *ptr == 'E') // read the exponent part
+ {
+ ptr++;
+
+ // read the sign of the exponent
+ if(*ptr == '+')
+ ptr++;
+ else if(*ptr == '-')
+ {
+ ptr++;
+ expsign = -1;
+ }
+
+ exponent = 0;
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ {
+ exponent *= 10;
+ exponent += *ptr - '0';
+ ptr++;
+ }
+ }
+ number = integer + decimal;
+ number *= sign * pow( (double)10, double( expsign * exponent ) );
+
+ return ptr;
+}
+
+void SvgImport::addGraphicContext()
+{
+ SvgGraphicsContext *gc = new SvgGraphicsContext;
+ // set as default
+ if( m_gc.current() )
+ *gc = *( m_gc.current() );
+ m_gc.push( gc );
+}
+
+void SvgImport::setupTransform( const QDomElement &e )
+{
+ SvgGraphicsContext *gc = m_gc.current();
+
+ QWMatrix mat = VPath::parseTransform( e.attribute( "transform" ) );
+ gc->matrix = mat * gc->matrix;
+}
+
+VObject* SvgImport::findObject( const QString &name, VGroup* group )
+{
+ if( ! group )
+ return 0L;
+
+ VObjectListIterator itr = group->objects();
+
+ for( uint objcount = 1; itr.current(); ++itr, objcount++ )
+ if( itr.current()->state() != VObject::deleted )
+ {
+ if( itr.current()->name() == name )
+ return itr.current();
+
+ if( dynamic_cast<VGroup *>( itr.current() ) )
+ {
+ VObject *obj = findObject( name, dynamic_cast<VGroup *>( itr.current() ) );
+ if( obj )
+ return obj;
+ }
+ }
+
+ return 0L;
+}
+
+VObject* SvgImport::findObject( const QString &name )
+{
+ QPtrVector<VLayer> vector;
+ m_document.layers().toVector( &vector );
+ for( int i = vector.count() - 1; i >= 0; i-- )
+ {
+ if ( vector[i]->state() != VObject::deleted )
+ {
+ VObject* obj = findObject( name, dynamic_cast<VGroup *>( vector[i] ) );
+ if( obj )
+ return obj;
+ }
+ }
+
+ return 0L;
+}
+
+SvgImport::GradientHelper* SvgImport::findGradient( const QString &id, const QString &href)
+{
+ // check if gradient was already parsed, and return it
+ if( m_gradients.contains( id ) )
+ return &m_gradients[ id ];
+
+ // check if gradient was stored for later parsing
+ if( !m_defs.contains( id ) )
+ return 0L;
+
+ QDomElement e = m_defs[ id ];
+ if(e.childNodes().count() == 0)
+ {
+ QString mhref = e.attribute("xlink:href").mid(1);
+
+ if(m_defs.contains(mhref))
+ return findGradient(mhref, id);
+ else
+ return 0L;
+ }
+ else
+ {
+ // ok parse gradient now
+ parseGradient( m_defs[ id ], m_defs[ href ] );
+ }
+
+ // return successfully parsed gradient or NULL
+ QString n;
+ if(href.isEmpty())
+ n = id;
+ else
+ n = href;
+
+ if( m_gradients.contains( n ) )
+ return &m_gradients[ n ];
+ else
+ return 0L;
+}
+
+QDomElement SvgImport::mergeStyles( const QDomElement &referencedBy, const QDomElement &referencedElement )
+{
+ // First use all the style attributes of the element being referenced.
+ QDomElement e = referencedElement;
+
+ // Now go through the style attributes of the element that is referencing and substitute the original ones.
+ if( !referencedBy.attribute( "color" ).isEmpty() )
+ e.setAttribute( "color", referencedBy.attribute( "color" ) );
+ if( !referencedBy.attribute( "fill" ).isEmpty() )
+ e.setAttribute( "fill", referencedBy.attribute( "fill" ) );
+ if( !referencedBy.attribute( "fill-rule" ).isEmpty() )
+ e.setAttribute( "fill-rule", referencedBy.attribute( "fill-rule" ) );
+ if( !referencedBy.attribute( "stroke" ).isEmpty() )
+ e.setAttribute( "stroke", referencedBy.attribute( "stroke" ) );
+ if( !referencedBy.attribute( "stroke-width" ).isEmpty() )
+ e.setAttribute( "stroke-width", referencedBy.attribute( "stroke-width" ) );
+ if( !referencedBy.attribute( "stroke-linejoin" ).isEmpty() )
+ e.setAttribute( "stroke-linejoin", referencedBy.attribute( "stroke-linejoin" ) );
+ if( !referencedBy.attribute( "stroke-linecap" ).isEmpty() )
+ e.setAttribute( "stroke-linecap", referencedBy.attribute( "stroke-linecap" ) );
+ if( !referencedBy.attribute( "stroke-dasharray" ).isEmpty() )
+ e.setAttribute( "stroke-dasharray", referencedBy.attribute( "stroke-dasharray" ) );
+ if( !referencedBy.attribute( "stroke-dashoffset" ).isEmpty() )
+ e.setAttribute( "stroke-dashoffset", referencedBy.attribute( "stroke-dashoffset" ) );
+ if( !referencedBy.attribute( "stroke-opacity" ).isEmpty() )
+ e.setAttribute( "stroke-opacity", referencedBy.attribute( "stroke-opacity" ) );
+ if( !referencedBy.attribute( "stroke-miterlimit" ).isEmpty() )
+ e.setAttribute( "stroke-miterlimit", referencedBy.attribute( "stroke-miterlimit" ) );
+ if( !referencedBy.attribute( "fill-opacity" ).isEmpty() )
+ e.setAttribute( "fill-opacity", referencedBy.attribute( "fill-opacity" ) );
+ if( !referencedBy.attribute( "opacity" ).isEmpty() )
+ e.setAttribute( "opacity", referencedBy.attribute( "opacity" ) );
+
+ // TODO merge style attribute too.
+
+ return e;
+}
+
+
+// Parsing functions
+// ---------------------------------------------------------------------------------------
+
+double SvgImport::parseUnit( const QString &unit, bool horiz, bool vert, KoRect bbox )
+{
+ // TODO : percentage?
+ double value = 0;
+ const char *start = unit.latin1();
+ if(!start) {
+ return 0;
+ }
+ const char *end = getNumber( start, value );
+
+ if( uint( end - start ) < unit.length() )
+ {
+ if( unit.right( 2 ) == "pt" )
+ value = ( value / 72.0 ) * DPI;
+ else if( unit.right( 2 ) == "cm" )
+ value = ( value / 2.54 ) * DPI;
+ else if( unit.right( 2 ) == "pc" )
+ value = ( value / 6.0 ) * DPI;
+ else if( unit.right( 2 ) == "mm" )
+ value = ( value / 25.4 ) * DPI;
+ else if( unit.right( 2 ) == "in" )
+ value = value * DPI;
+ else if( unit.right( 2 ) == "pt" )
+ value = ( value / 72.0 ) * DPI;
+ else if( unit.right( 2 ) == "em" )
+ value = value * m_gc.current()->font.pointSize() / ( sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 ) );
+ else if( unit.right( 1 ) == "%" )
+ {
+ if( horiz && vert )
+ value = ( value / 100.0 ) * (sqrt( pow( bbox.width(), 2 ) + pow( bbox.height(), 2 ) ) / sqrt( 2.0 ) );
+ else if( horiz )
+ value = ( value / 100.0 ) * bbox.width();
+ else if( vert )
+ value = ( value / 100.0 ) * bbox.height();
+ }
+ }
+ /*else
+ {
+ if( m_gc.current() )
+ {
+ if( horiz && vert )
+ value *= sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 );
+ else if( horiz )
+ value /= m_gc.current()->matrix.m11();
+ else if( vert )
+ value /= m_gc.current()->matrix.m22();
+ }
+ }*/
+ return value;
+}
+
+QColor SvgImport::parseColor( const QString &rgbColor )
+{
+ int r, g, b;
+ keywordToRGB( rgbColor, r, g, b );
+ return QColor( r, g, b );
+}
+
+void SvgImport::parseColor( VColor &color, const QString &s )
+{
+ if( s.startsWith( "rgb(" ) )
+ {
+ QString parse = s.stripWhiteSpace();
+ QStringList colors = QStringList::split( ',', parse );
+ QString r = colors[0].right( ( colors[0].length() - 4 ) );
+ QString g = colors[1];
+ QString b = colors[2].left( ( colors[2].length() - 1 ) );
+
+ if( r.contains( "%" ) )
+ {
+ r = r.left( r.length() - 1 );
+ r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( g.contains( "%" ) )
+ {
+ g = g.left( g.length() - 1 );
+ g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( b.contains( "%" ) )
+ {
+ b = b.left( b.length() - 1 );
+ b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
+ }
+
+ QColor c( r.toInt(), g.toInt(), b.toInt() );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+ else if( s == "currentColor" )
+ {
+ SvgGraphicsContext *gc = m_gc.current();
+ color = gc->color;
+ }
+ else
+ {
+ QString rgbColor = s.stripWhiteSpace();
+ QColor c;
+ if( rgbColor.startsWith( "#" ) )
+ c.setNamedColor( rgbColor );
+ else
+ c = parseColor( rgbColor );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+}
+
+void SvgImport::parseColorStops( VGradient *gradient, const QDomElement &e )
+{
+ VColor c;
+ for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement stop = n.toElement();
+ if( stop.tagName() == "stop" )
+ {
+ float offset;
+ QString temp = stop.attribute( "offset" );
+ if( temp.contains( '%' ) )
+ {
+ temp = temp.left( temp.length() - 1 );
+ offset = temp.toFloat() / 100.0;
+ }
+ else
+ offset = temp.toFloat();
+
+ if( !stop.attribute( "stop-color" ).isEmpty() )
+ parseColor( c, stop.attribute( "stop-color" ) );
+ else
+ {
+ // try style attr
+ QString style = stop.attribute( "style" ).simplifyWhiteSpace();
+ QStringList substyles = QStringList::split( ';', style );
+ for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ QStringList substyle = QStringList::split( ':', (*it) );
+ QString command = substyle[0].stripWhiteSpace();
+ QString params = substyle[1].stripWhiteSpace();
+ if( command == "stop-color" )
+ parseColor( c, params );
+ if( command == "stop-opacity" )
+ c.setOpacity( params.toDouble() );
+ }
+
+ }
+ if( !stop.attribute( "stop-opacity" ).isEmpty() )
+ c.setOpacity( stop.attribute( "stop-opacity" ).toDouble() );
+ gradient->addStop( c, offset, 0.5 );
+ }
+ }
+}
+
+void SvgImport::parseGradient( const QDomElement &e , const QDomElement &referencedBy)
+{
+ // IMPROVEMENTS:
+ // - Store the parsed colorstops in some sort of a cache so they don't need to be parsed again.
+ // - A gradient inherits attributes it does not have from the referencing gradient.
+ // - Gradients with no color stops have no fill or stroke.
+ // - Gradients with one color stop have a solid color.
+
+ SvgGraphicsContext *gc = m_gc.current();
+ if( !gc ) return;
+
+ GradientHelper gradhelper;
+ gradhelper.gradient.clearStops();
+ gradhelper.gradient.setRepeatMethod( VGradient::none );
+
+ if(e.childNodes().count() == 0)
+ {
+ QString href = e.attribute("xlink:href").mid(1);
+
+ if(href.isEmpty())
+ {
+ //gc->fill.setType( VFill::none ); // <--- TODO Fill OR Stroke are none
+ return;
+ }
+ else
+ {
+ // copy the referenced gradient if found
+ GradientHelper *pGrad = findGradient( href );
+ if( pGrad )
+ gradhelper = *pGrad;
+ }
+ }
+
+ // Use the gradient that is referencing, or if there isn't one, the original gradient.
+ QDomElement b;
+ if( !referencedBy.isNull() )
+ b = referencedBy;
+ else
+ b = e;
+
+ QString id = b.attribute("id");
+ if( !id.isEmpty() )
+ {
+ // Copy existing gradient if it exists
+ if( m_gradients.find( id ) != m_gradients.end() )
+ gradhelper.gradient = m_gradients[ id ].gradient;
+ }
+
+ gradhelper.bbox = b.attribute( "gradientUnits" ) != "userSpaceOnUse";
+
+ // parse color prop
+ VColor c = m_gc.current()->color;
+
+ if( !b.attribute( "color" ).isEmpty() )
+ {
+ parseColor( c, b.attribute( "color" ) );
+ }
+ else
+ {
+ // try style attr
+ QString style = b.attribute( "style" ).simplifyWhiteSpace();
+ QStringList substyles = QStringList::split( ';', style );
+ for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ QStringList substyle = QStringList::split( ':', (*it) );
+ QString command = substyle[0].stripWhiteSpace();
+ QString params = substyle[1].stripWhiteSpace();
+ if( command == "color" )
+ parseColor( c, params );
+ }
+ }
+ m_gc.current()->color = c;
+
+ if( b.tagName() == "linearGradient" )
+ {
+ if( gradhelper.bbox )
+ {
+ gradhelper.gradient.setOrigin( KoPoint( toPercentage( b.attribute( "x1", "0%" ) ), toPercentage( b.attribute( "y1", "0%" ) ) ) );
+ gradhelper.gradient.setVector( KoPoint( toPercentage( b.attribute( "x2", "100%" ) ), toPercentage( b.attribute( "y2", "0%" ) ) ) );
+ }
+ else
+ {
+ gradhelper.gradient.setOrigin( KoPoint( b.attribute( "x1" ).toDouble(), b.attribute( "y1" ).toDouble() ) );
+ gradhelper.gradient.setVector( KoPoint( b.attribute( "x2" ).toDouble(), b.attribute( "y2" ).toDouble() ) );
+ }
+ gradhelper.gradient.setType( VGradient::linear );
+ }
+ else
+ {
+ if( gradhelper.bbox )
+ {
+ gradhelper.gradient.setOrigin( KoPoint( toPercentage( b.attribute( "cx", "50%" ) ), toPercentage( b.attribute( "cy", "50%" ) ) ) );
+ gradhelper.gradient.setVector( KoPoint( toPercentage( b.attribute( "cx", "50%" ) ) + toPercentage( b.attribute( "r", "50%" ) ), toPercentage( b.attribute( "cy", "50%" ) ) ) );
+ gradhelper.gradient.setFocalPoint( KoPoint( toPercentage( b.attribute( "fx", "50%" ) ), toPercentage( b.attribute( "fy", "50%" ) ) ) );
+ }
+ else
+ {
+ gradhelper.gradient.setOrigin( KoPoint( b.attribute( "cx" ).toDouble(), b.attribute( "cy" ).toDouble() ) );
+ gradhelper.gradient.setFocalPoint( KoPoint( b.attribute( "fx" ).toDouble(), b.attribute( "fy" ).toDouble() ) );
+ gradhelper.gradient.setVector( KoPoint( b.attribute( "cx" ).toDouble() + b.attribute( "r" ).toDouble(), b.attribute( "cy" ).toDouble() ) );
+ }
+ gradhelper.gradient.setType( VGradient::radial );
+ }
+ // handle spread method
+ QString spreadMethod = b.attribute( "spreadMethod" );
+ if( !spreadMethod.isEmpty() )
+ {
+ if( spreadMethod == "reflect" )
+ gradhelper.gradient.setRepeatMethod( VGradient::reflect );
+ else if( spreadMethod == "repeat" )
+ gradhelper.gradient.setRepeatMethod( VGradient::repeat );
+ else
+ gradhelper.gradient.setRepeatMethod( VGradient::none );
+ }
+ else
+ gradhelper.gradient.setRepeatMethod( VGradient::none );
+
+ // Parse the color stops. The referencing gradient does not have colorstops,
+ // so use the stops from the gradient it references to (e in this case and not b)
+ parseColorStops( &gradhelper.gradient, e );
+ //gradient.setGradientTransform( parseTransform( e.attribute( "gradientTransform" ) ) );
+ gradhelper.gradientTransform = VPath::parseTransform( b.attribute( "gradientTransform" ) );
+ m_gradients.insert( b.attribute( "id" ), gradhelper );
+}
+
+void SvgImport::parsePA( VObject *obj, SvgGraphicsContext *gc, const QString &command, const QString &params )
+{
+ VColor fillcolor = gc->fill.color();
+ VColor strokecolor = gc->stroke.color();
+
+ if( params == "inherit" ) return;
+
+ if( command == "fill" )
+ {
+ if( params == "none" )
+ gc->fill.setType( VFill::none );
+ else if( params.startsWith( "url(" ) )
+ {
+ unsigned int start = params.find("#") + 1;
+ unsigned int end = params.findRev(")");
+ QString key = params.mid( start, end - start );
+ GradientHelper *gradHelper = findGradient( key );
+ if( gradHelper )
+ {
+ gc->fill.gradient() = gradHelper->gradient;
+
+ if( gradHelper->bbox )
+ {
+ // adjust to bbox
+ KoRect bbox = obj->boundingBox();
+ //kdDebug() << "bbox x : " << bbox.x() << endl;
+ //kdDebug() << "!!!!!!bbox y : " << bbox.y() << endl;
+ //kdDebug() << gc->fill.gradient().origin().x() << endl;
+ //kdDebug() << gc->fill.gradient().vector().x() << endl;
+ double offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().origin().x() ), true, false, bbox );
+ double offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().origin().y() ), false, true, bbox );
+ gc->fill.gradient().setOrigin( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ if(gc->fill.gradient().type() == VGradient::radial)
+ {
+ offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().focalPoint().x() ), true, false, bbox );
+ offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().focalPoint().y() ), false, true, bbox );
+ gc->fill.gradient().setFocalPoint( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ }
+ offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().vector().x() ), true, false, bbox );
+ offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().vector().y() ), false, true, bbox );
+ gc->fill.gradient().setVector( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ //kdDebug() << offsety << endl;
+ //kdDebug() << gc->fill.gradient().origin().x() << endl;
+ //kdDebug() << gc->fill.gradient().origin().y() << endl;
+ //kdDebug() << gc->fill.gradient().vector().x() << endl;
+ //kdDebug() << gc->fill.gradient().vector().y() << endl;
+ }
+ gc->fill.gradient().transform( gradHelper->gradientTransform );
+
+ if( !gradHelper->bbox )
+ gc->fill.gradient().transform( gc->matrix );
+
+ gc->fill.setType( VFill::grad );
+ }
+ else
+ gc->fill.setType( VFill::none );
+ }
+ else
+ {
+ parseColor( fillcolor, params );
+ gc->fill.setType( VFill::solid );
+ }
+ }
+ else if( command == "fill-rule" )
+ {
+ if( params == "nonzero" )
+ gc->fillRule = winding;
+ else if( params == "evenodd" )
+ gc->fillRule = evenOdd;
+ }
+ else if( command == "stroke" )
+ {
+ if( params == "none" )
+ gc->stroke.setType( VStroke::none );
+ else if( params.startsWith( "url(" ) )
+ {
+ unsigned int start = params.find("#") + 1;
+ unsigned int end = params.findRev(")");
+ QString key = params.mid( start, end - start );
+
+ GradientHelper *gradHelper = findGradient( key );
+ if( gradHelper )
+ {
+ gc->stroke.gradient() = gradHelper->gradient;
+ gc->stroke.gradient().transform( gradHelper->gradientTransform );
+ gc->stroke.gradient().transform( gc->matrix );
+ gc->stroke.setType( VStroke::grad );
+ }
+ else
+ gc->stroke.setType( VStroke::none );
+ }
+ else
+ {
+ parseColor( strokecolor, params );
+ gc->stroke.setType( VStroke::solid );
+ }
+ }
+ else if( command == "stroke-width" )
+ gc->stroke.setLineWidth( parseUnit( params, true, true, m_outerRect ) );
+ else if( command == "stroke-linejoin" )
+ {
+ if( params == "miter" )
+ gc->stroke.setLineJoin( VStroke::joinMiter );
+ else if( params == "round" )
+ gc->stroke.setLineJoin( VStroke::joinRound );
+ else if( params == "bevel" )
+ gc->stroke.setLineJoin( VStroke::joinBevel );
+ }
+ else if( command == "stroke-linecap" )
+ {
+ if( params == "butt" )
+ gc->stroke.setLineCap( VStroke::capButt );
+ else if( params == "round" )
+ gc->stroke.setLineCap( VStroke::capRound );
+ else if( params == "square" )
+ gc->stroke.setLineCap( VStroke::capSquare );
+ }
+ else if( command == "stroke-miterlimit" )
+ gc->stroke.setMiterLimit( params.toFloat() );
+ else if( command == "stroke-dasharray" )
+ {
+ QValueList<float> array;
+ if(params != "none")
+ {
+ // with "stroke-dasharray", the separator is a white space
+ // inside style attribute, stroke-dasharray is separated by comma (,)
+ QStringList dashes = QStringList::split( QRegExp("[\\s,]"), params );
+ for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
+ array.append( (*it).toFloat() );
+ }
+ gc->stroke.dashPattern().setArray( array );
+ }
+ else if( command == "stroke-dashoffset" )
+ gc->stroke.dashPattern().setOffset( params.toFloat() );
+ // handle opacity
+ else if( command == "stroke-opacity" )
+ strokecolor.setOpacity( fromPercentage( params ) );
+ else if( command == "fill-opacity" )
+ fillcolor.setOpacity( fromPercentage( params ) );
+ else if( command == "opacity" )
+ {
+ fillcolor.setOpacity( fromPercentage( params ) );
+ strokecolor.setOpacity( fromPercentage( params ) );
+ }
+ else if( command == "font-family" )
+ {
+ QString family = params;
+ family.replace( '\'' , ' ' );
+ gc->font.setFamily( family );
+ }
+ else if( command == "font-size" )
+ {
+ float pointSize = parseUnit( params );
+ gc->font.setPointSizeFloat( pointSize * getScalingFromMatrix( gc->matrix ) );
+ }
+ else if( command == "font-weight" )
+ {
+ int weight = QFont::Normal;
+
+ // map svg weight to qt weight
+ // svg value qt value
+ // 100,200,300 1, 17, 33
+ // 400 50 (normal)
+ // 500,600 58,66
+ // 700 75 (bold)
+ // 800,900 87,99
+
+ if( params == "bold" )
+ weight = QFont::Bold;
+ else if( params == "lighter" )
+ {
+ weight = gc->font.weight();
+ if( weight <= 17 )
+ weight = 1;
+ else if( weight <= 33 )
+ weight = 17;
+ else if( weight <= 50 )
+ weight = 33;
+ else if( weight <= 58 )
+ weight = 50;
+ else if( weight <= 66 )
+ weight = 58;
+ else if( weight <= 75 )
+ weight = 66;
+ else if( weight <= 87 )
+ weight = 75;
+ else if( weight <= 99 )
+ weight = 87;
+ }
+ else if( params == "bolder" )
+ {
+ weight = gc->font.weight();
+ if( weight >= 87 )
+ weight = 99;
+ else if( weight >= 75 )
+ weight = 87;
+ else if( weight >= 66 )
+ weight = 75;
+ else if( weight >= 58 )
+ weight = 66;
+ else if( weight >= 50 )
+ weight = 58;
+ else if( weight >= 33 )
+ weight = 50;
+ else if( weight >= 17 )
+ weight = 50;
+ else if( weight >= 1 )
+ weight = 17;
+ }
+ else
+ {
+ bool ok;
+ // try to read numerical weight value
+ weight = params.toInt( &ok, 10 );
+
+ if( !ok )
+ return;
+
+ switch( weight )
+ {
+ case 100: weight = 1; break;
+ case 200: weight = 17; break;
+ case 300: weight = 33; break;
+ case 400: weight = 50; break;
+ case 500: weight = 58; break;
+ case 600: weight = 66; break;
+ case 700: weight = 75; break;
+ case 800: weight = 87; break;
+ case 900: weight = 99; break;
+ }
+ }
+ gc->font.setWeight( weight );
+ }
+ else if( command == "text-decoration" )
+ {
+ if( params == "line-through" )
+ gc->font.setStrikeOut( true );
+ else if( params == "underline" )
+ gc->font.setUnderline( true );
+ }
+ else if( command == "color" )
+ {
+ VColor color;
+ parseColor( color, params );
+ gc->color = color;
+ }
+ if( gc->fill.type() != VFill::none )
+ gc->fill.setColor( fillcolor, false );
+ //if( gc->stroke.type() == VStroke::solid )
+ gc->stroke.setColor( strokecolor );
+}
+
+void SvgImport::parseStyle( VObject *obj, const QDomElement &e )
+{
+ SvgGraphicsContext *gc = m_gc.current();
+ if( !gc ) return;
+
+ // try normal PA
+ if( !e.attribute( "color" ).isEmpty() )
+ parsePA( obj, gc, "color", e.attribute( "color" ) );
+ if( !e.attribute( "fill" ).isEmpty() )
+ parsePA( obj, gc, "fill", e.attribute( "fill" ) );
+ if( !e.attribute( "fill-rule" ).isEmpty() )
+ parsePA( obj, gc, "fill-rule", e.attribute( "fill-rule" ) );
+ if( !e.attribute( "stroke" ).isEmpty() )
+ parsePA( obj, gc, "stroke", e.attribute( "stroke" ) );
+ if( !e.attribute( "stroke-width" ).isEmpty() )
+ parsePA( obj, gc, "stroke-width", e.attribute( "stroke-width" ) );
+ if( !e.attribute( "stroke-linejoin" ).isEmpty() )
+ parsePA( obj, gc, "stroke-linejoin", e.attribute( "stroke-linejoin" ) );
+ if( !e.attribute( "stroke-linecap" ).isEmpty() )
+ parsePA( obj, gc, "stroke-linecap", e.attribute( "stroke-linecap" ) );
+ if( !e.attribute( "stroke-dasharray" ).isEmpty() )
+ parsePA( obj, gc, "stroke-dasharray", e.attribute( "stroke-dasharray" ) );
+ if( !e.attribute( "stroke-dashoffset" ).isEmpty() )
+ parsePA( obj, gc, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) );
+ if( !e.attribute( "stroke-opacity" ).isEmpty() )
+ parsePA( obj, gc, "stroke-opacity", e.attribute( "stroke-opacity" ) );
+ if( !e.attribute( "stroke-miterlimit" ).isEmpty() )
+ parsePA( obj, gc, "stroke-miterlimit", e.attribute( "stroke-miterlimit" ) );
+ if( !e.attribute( "fill-opacity" ).isEmpty() )
+ parsePA( obj, gc, "fill-opacity", e.attribute( "fill-opacity" ) );
+ if( !e.attribute( "opacity" ).isEmpty() )
+ parsePA( obj, gc, "opacity", e.attribute( "opacity" ) );
+
+ // try style attr
+ QString style = e.attribute( "style" ).simplifyWhiteSpace();
+ QStringList substyles = QStringList::split( ';', style );
+ for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ QStringList substyle = QStringList::split( ':', (*it) );
+ QString command = substyle[0].stripWhiteSpace();
+ QString params = substyle[1].stripWhiteSpace();
+ parsePA( obj, gc, command, params );
+ }
+
+ if(!obj)
+ return;
+
+ obj->setFill( gc->fill );
+ if( dynamic_cast<VPath *>( obj ) )
+ dynamic_cast<VPath *>( obj )->setFillRule( gc->fillRule );
+ // stroke scaling
+ double lineWidth = gc->stroke.lineWidth();
+ gc->stroke.setLineWidth( lineWidth * getScalingFromMatrix( gc->matrix ) );
+ obj->setStroke( gc->stroke );
+ gc->stroke.setLineWidth( lineWidth );
+}
+
+void SvgImport::parseFont( const QDomElement &e )
+{
+ SvgGraphicsContext *gc = m_gc.current();
+ if( !gc ) return;
+
+ if( ! e.attribute( "font-family" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "font-family", e.attribute( "font-family" ) );
+ if( ! e.attribute( "font-size" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "font-size", e.attribute( "font-size" ) );
+ if( ! e.attribute( "font-weight" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "font-weight", e.attribute( "font-weight" ) );
+ if( ! e.attribute( "text-decoration" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "text-decoration", e.attribute( "text-decoration" ) );
+}
+
+void SvgImport::parseUse( VGroup *grp, const QDomElement &e )
+{
+ QString id = e.attribute( "xlink:href" );
+
+ if( !id.isEmpty() )
+ {
+ addGraphicContext();
+ setupTransform( e );
+
+ QString key = id.mid( 1 );
+
+ if( !e.attribute( "x" ).isEmpty() && !e.attribute( "y" ).isEmpty() )
+ {
+ double tx = e.attribute( "x" ).toDouble();
+ double ty = e.attribute( "y" ).toDouble();
+
+ m_gc.current()->matrix.translate(tx,ty);
+ }
+
+ if(m_defs.contains(key))
+ {
+ QDomElement a = m_defs[key];
+ if(a.tagName() == "g" || a.tagName() == "a")
+ parseGroup( grp, a);
+ else
+ {
+ // Create the object with the merged styles.
+ // The object inherits all style attributes from the use tag, but keeps it's own attributes.
+ // So, not just use the style attributes of the use tag, but merge them first.
+ createObject( grp, a, VObject::normal, mergeStyles(e, a) );
+ }
+ }
+ delete( m_gc.pop() );
+ }
+}
+
+void SvgImport::parseGroup( VGroup *grp, const QDomElement &e )
+{
+ for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement b = n.toElement();
+ if( b.isNull() ) continue;
+
+ // treat svg link <a> as group so we don't miss its child elements
+ if( b.tagName() == "g" || b.tagName() == "a" )
+ {
+ VGroup *group;
+ if ( grp )
+ group = new VGroup( grp );
+ else
+ group = new VGroup( &m_document );
+
+ addGraphicContext();
+ setupTransform( b );
+ parseStyle( group, b );
+ parseFont( b );
+ parseGroup( group, b );
+
+ // handle id
+ if( !b.attribute("id").isEmpty() )
+ group->setName( b.attribute("id") );
+ if( grp )
+ grp->append( group );
+ else
+ m_document.append( group );
+ delete( m_gc.pop() );
+ continue;
+ }
+ if( b.tagName() == "defs" )
+ {
+ parseDefs( b );
+ continue;
+ }
+ else if( b.tagName() == "linearGradient" || b.tagName() == "radialGradient" )
+ {
+ parseGradient( b );
+ continue;
+ }
+ if( b.tagName() == "rect" ||
+ b.tagName() == "ellipse" ||
+ b.tagName() == "circle" ||
+ b.tagName() == "line" ||
+ b.tagName() == "polyline" ||
+ b.tagName() == "polygon" ||
+ b.tagName() == "path" ||
+ b.tagName() == "image" )
+ {
+ createObject( grp, b );
+ continue;
+ }
+ else if( b.tagName() == "text" )
+ {
+ createText( grp, b );
+ continue;
+ }
+ else if( b.tagName() == "use" )
+ {
+ parseUse( grp, b );
+ continue;
+ }
+ }
+}
+
+void SvgImport::parseDefs( const QDomElement &e )
+{
+ for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement b = n.toElement();
+ if( b.isNull() ) continue;
+
+ QString definition = b.attribute( "id" );
+ if( !definition.isEmpty() )
+ {
+ if( !m_defs.contains( definition ) )
+ m_defs.insert( definition, b );
+ }
+ }
+}
+
+
+// Creating functions
+// ---------------------------------------------------------------------------------------
+
+void SvgImport::createText( VGroup *grp, const QDomElement &b )
+{
+ const double pathLength = 10.0;
+
+ VText *text = 0L;
+ QString content;
+ QString anchor;
+ VSubpath base( 0L );
+ VPath *path = 0L;
+ double offset = 0.0;
+
+ addGraphicContext();
+ setupTransform( b );
+
+ parseFont( b );
+
+ if( ! b.attribute( "text-anchor" ).isEmpty() )
+ anchor = b.attribute( "text-anchor" );
+
+ if( b.hasChildNodes() )
+ {
+ if( base.isEmpty() && ! b.attribute( "x" ).isEmpty() && ! b.attribute( "y" ).isEmpty() )
+ {
+ double x = parseUnit( b.attribute( "x" ) );
+ double y = parseUnit( b.attribute( "y" ) );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + pathLength, y ) );
+ }
+
+ for( QDomNode n = b.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if( e.isNull() )
+ {
+ content += n.toCharacterData().data();
+ }
+ else if( e.tagName() == "textPath" )
+ {
+ if( e.attribute( "xlink:href" ).isEmpty() )
+ continue;
+
+ QString key = e.attribute( "xlink:href" ).mid( 1 );
+ if( ! m_defs.contains(key) )
+ {
+ // try to find referenced object in document
+ VObject* obj = findObject( key );
+ // try to find referenced object in actual group, which is not yet part of document
+ if( ! obj )
+ obj = findObject( key, grp );
+ if( obj )
+ path = dynamic_cast<VPath*>( obj );
+ }
+ else
+ {
+ QDomElement p = m_defs[key];
+ createObject( grp, p, VObject::deleted);
+ }
+ if( ! path )
+ continue;
+ base = *path->paths().getFirst();
+ content += e.text();
+
+ if( ! e.attribute( "startOffset" ).isEmpty() )
+ {
+ QString start = e.attribute( "startOffset" );
+ if( start.endsWith( "%" ) )
+ offset = 0.01 * start.remove( '%' ).toDouble();
+ else
+ {
+ float pathLength = 0;
+ VSubpathIterator pIt( base );
+
+ for( ; pIt.current(); ++pIt )
+ pathLength += pIt.current()->length();
+
+ if( pathLength > 0.0 )
+ offset = start.toDouble() / pathLength;
+ }
+ }
+ }
+ else if( e.tagName() == "tspan" )
+ {
+ // only use text of tspan element, as we are not supporting text
+ // with different styles
+ content += e.text();
+ if( base.isEmpty() && ! e.attribute( "x" ).isEmpty() && ! e.attribute( "y" ).isEmpty() )
+ {
+ QStringList posX = QStringList::split( ", ", e.attribute( "x" ) );
+ QStringList posY = QStringList::split( ", ", e.attribute( "y" ) );
+ if( posX.count() && posY.count() )
+ {
+ double x = parseUnit( posX.first() );
+ double y = parseUnit( posY.first() );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + pathLength, y ) );
+ }
+ }
+ }
+ else if( e.tagName() == "tref" )
+ {
+ if( e.attribute( "xlink:href" ).isEmpty() )
+ continue;
+
+ QString key = e.attribute( "xlink:href" ).mid( 1 );
+ if( ! m_defs.contains(key) )
+ {
+ // try to find referenced object in document
+ VObject* obj = findObject( key );
+ // try to find referenced object in actual group, which is not yet part of document
+ if( ! obj )
+ obj = findObject( key, grp );
+ if( obj )
+ content += dynamic_cast<VText*>( obj )->text();
+ }
+ else
+ {
+ QDomElement p = m_defs[key];
+ content += p.text();
+ }
+ }
+ else
+ continue;
+
+ if( ! e.attribute( "text-anchor" ).isEmpty() )
+ anchor = e.attribute( "text-anchor" );
+ }
+ text = new VText( m_gc.current()->font, base, VText::Above, VText::Left, content.simplifyWhiteSpace() );
+ }
+ else
+ {
+ VSubpath base( 0L );
+ double x = parseUnit( b.attribute( "x" ) );
+ double y = parseUnit( b.attribute( "y" ) );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + pathLength, y ) );
+ text = new VText( m_gc.current()->font, base, VText::Above, VText::Left, b.text().simplifyWhiteSpace() );
+ }
+
+ if( text )
+ {
+ text->setParent( &m_document );
+
+ parseStyle( text, b );
+
+ text->setFont( m_gc.current()->font );
+
+ VTransformCmd trafo( 0L, m_gc.current()->matrix );
+ trafo.visit( *text );
+
+ if( !b.attribute("id").isEmpty() )
+ text->setName( b.attribute("id") );
+
+ if( anchor == "middle" )
+ text->setAlignment( VText::Center );
+ else if( anchor == "end" )
+ text->setAlignment( VText::Right );
+
+ if( offset > 0.0 )
+ text->setOffset( offset );
+
+ if( grp )
+ grp->append( text );
+ else
+ m_document.append( text );
+ }
+
+ delete( m_gc.pop() );
+}
+
+void SvgImport::createObject( VGroup *grp, const QDomElement &b, const VObject::VState state, const QDomElement &style )
+{
+ VObject *obj = 0L;
+
+ addGraphicContext();
+ setupTransform( b );
+
+ if( b.tagName() == "rect" )
+ {
+ double x = parseUnit( b.attribute( "x" ), true, false, m_outerRect );
+ double y = parseUnit( b.attribute( "y" ), false, true, m_outerRect );
+ double width = parseUnit( b.attribute( "width" ), true, false, m_outerRect );
+ double height = parseUnit( b.attribute( "height" ), false, true, m_outerRect );
+ double rx = parseUnit( b.attribute( "rx" ) );
+ double ry = parseUnit( b.attribute( "ry" ) );
+ obj = new VRectangle( 0L, KoPoint( x, height + y ) , width, height, rx, ry );
+ }
+ else if( b.tagName() == "ellipse" )
+ {
+ double rx = parseUnit( b.attribute( "rx" ) );
+ double ry = parseUnit( b.attribute( "ry" ) );
+ double left = parseUnit( b.attribute( "cx" ) ) - rx;
+ double top = parseUnit( b.attribute( "cy" ) ) - ry;
+ obj = new VEllipse( 0L, KoPoint( left, top ), rx * 2.0, ry * 2.0 );
+ }
+ else if( b.tagName() == "circle" )
+ {
+ double r = parseUnit( b.attribute( "r" ) );
+ double left = parseUnit( b.attribute( "cx" ) ) - r;
+ double top = parseUnit( b.attribute( "cy" ) ) - r;
+ obj = new VEllipse( 0L, KoPoint( left, top ), r * 2.0, r * 2.0 );
+ }
+ else if( b.tagName() == "line" )
+ {
+ VPath *path = new VPath( &m_document );
+ double x1 = b.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x1" ) );
+ double y1 = b.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y1" ) );
+ double x2 = b.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x2" ) );
+ double y2 = b.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y2" ) );
+ path->moveTo( KoPoint( x1, y1 ) );
+ path->lineTo( KoPoint( x2, y2 ) );
+ obj = path;
+ }
+ else if( b.tagName() == "polyline" || b.tagName() == "polygon" )
+ {
+ VPath *path = new VPath( &m_document );
+ bool bFirst = true;
+
+ QString points = b.attribute( "points" ).simplifyWhiteSpace();
+ points.replace( ',', ' ' );
+ points.remove( '\r' );
+ points.remove( '\n' );
+ QStringList pointList = QStringList::split( ' ', points );
+ for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); ++it)
+ {
+ KoPoint point;
+ point.setX( (*it).toDouble() );
+ ++it;
+ point.setY( (*it).toDouble() );
+ if( bFirst )
+ {
+ path->moveTo( point );
+ bFirst = false;
+ }
+ else
+ path->lineTo( point );
+ }
+ if( b.tagName() == "polygon" ) path->close();
+ obj = path;
+ }
+ else if( b.tagName() == "path" )
+ {
+ VPath *path = new VPath( &m_document );
+ path->loadSvgPath( b.attribute( "d" ) );
+ obj = path;
+ }
+ else if( b.tagName() == "image" )
+ {
+ QString fname = b.attribute("xlink:href");
+ obj = new VImage( 0L, fname );
+ }
+
+ if( !obj )
+ return;
+
+ if (state != VObject::normal)
+ obj->setState(state);
+
+ VTransformCmd trafo( 0L, m_gc.current()->matrix );
+ trafo.visit( *obj );
+
+ if( !style.isNull() )
+ parseStyle( obj, style );
+ else
+ parseStyle( obj, b );
+
+ // handle id
+ if( !b.attribute("id").isEmpty() )
+ obj->setName( b.attribute("id") );
+ if( grp )
+ grp->append( obj );
+ else
+ m_document.append( obj );
+
+ delete( m_gc.pop() );
+}
+
+#include <svgimport.moc>
diff --git a/filters/karbon/svg/svgimport.h b/filters/karbon/svg/svgimport.h
new file mode 100644
index 00000000..a558c1fc
--- /dev/null
+++ b/filters/karbon/svg/svgimport.h
@@ -0,0 +1,102 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __SVGIMPORT_H__
+#define __SVGIMPORT_H__
+
+#include <KoFilter.h>
+#include <qdom.h>
+#include <qmap.h>
+#include <qptrstack.h>
+#include <core/vdocument.h>
+#include <core/vgradient.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vfillrule.h>
+#include "svggraphiccontext.h"
+
+#include <vobject.h>
+
+class VGroup;
+class VPath;
+
+class SvgImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ SvgImport(KoFilter *parent, const char *name, const QStringList&);
+ virtual ~SvgImport();
+
+ virtual KoFilter::ConversionStatus convert(const QCString& from, const QCString& to);
+
+protected:
+ class GradientHelper
+ {
+ public:
+ GradientHelper()
+ {
+ bbox = true;
+ }
+ VGradient gradient;
+ bool bbox;
+ QWMatrix gradientTransform;
+ };
+
+ void parseGroup( VGroup *, const QDomElement & );
+ void parseDefs( const QDomElement & );
+ void parseUse( VGroup *, const QDomElement & );
+ void parseStyle( VObject *, const QDomElement & );
+ void parsePA( VObject *, SvgGraphicsContext *, const QString &, const QString & );
+ void parseGradient( const QDomElement &, const QDomElement &referencedBy = QDomElement() );
+ void parseColorStops( VGradient *, const QDomElement & );
+ double parseUnit( const QString &, bool horiz = false, bool vert = false, KoRect bbox = KoRect() );
+ void parseColor( VColor &, const QString & );
+ QColor parseColor( const QString & );
+ double toPercentage( QString );
+ double fromPercentage( QString );
+ void setupTransform( const QDomElement & );
+ void addGraphicContext();
+ QDomDocument inpdoc;
+ QDomDocument outdoc;
+ void convert();
+ void createObject( VGroup *grp, const QDomElement &, VObject::VState state = VObject::normal, const QDomElement &style = QDomElement() );
+ void createText( VGroup *, const QDomElement & );
+ void parseFont( const QDomElement & );
+ // find object with given id in document
+ VObject* findObject( const QString &name );
+ // find object with given id in given group
+ VObject* findObject( const QString &name, VGroup * );
+ // find gradient with given id in gradient map
+ GradientHelper* findGradient( const QString &id, const QString &href = 0 );
+
+ // Determine scaling factor from given matrix
+ double getScalingFromMatrix( QWMatrix &matrix );
+
+ QDomElement mergeStyles( const QDomElement &, const QDomElement & );
+
+private:
+ VDocument m_document;
+ QPtrStack<SvgGraphicsContext> m_gc;
+ QMap<QString, GradientHelper> m_gradients;
+ QMap<QString, QDomElement> m_defs;
+ KoRect m_outerRect;
+};
+
+#endif
diff --git a/filters/karbon/wmf/Makefile.am b/filters/karbon/wmf/Makefile.am
new file mode 100644
index 00000000..38acbe44
--- /dev/null
+++ b/filters/karbon/wmf/Makefile.am
@@ -0,0 +1,27 @@
+
+INCLUDES= \
+ -I$(srcdir) \
+ $(KWMF_INCLUDES) \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/commands \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = libwmfimport.la libwmfexport.la
+
+libwmfimport_la_LDFLAGS = -module $(KDE_PLUGIN)
+libwmfimport_la_LIBADD = $(KOFFICE_LIBS) $(LIB_KOWMF) ../../../karbon/libkarboncommon.la
+libwmfimport_la_SOURCES = wmfimport.cc wmfimportparser.cc
+
+libwmfexport_la_LDFLAGS = -module $(KDE_PLUGIN)
+libwmfexport_la_LIBADD = $(KOFFICE_LIBS) $(LIB_KOWMF) ../../../karbon/libkarboncommon.la
+libwmfexport_la_SOURCES = wmfexport.cc
+
+noinst_HEADERS = wmfimport.h wmfimportparser.h wmfexport.h
+
+METASOURCES = AUTO
+
+service_DATA = karbon_wmf_import.desktop karbon_wmf_export.desktop
+servicedir = $(kde_servicesdir)
diff --git a/filters/karbon/wmf/karbon_wmf_export.desktop b/filters/karbon/wmf/karbon_wmf_export.desktop
new file mode 100644
index 00000000..d859d274
--- /dev/null
+++ b/filters/karbon/wmf/karbon_wmf_export.desktop
@@ -0,0 +1,63 @@
+[Desktop Entry]
+Icon=
+Name=Karbon14 WMF Export Filter
+Name[ar]=مِرْشَح تصدير WMF لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в WMF
+Name[br]=Sil ezporzh WMF evit Karbon14
+Name[ca]=Filtre d'exportació WMF per a Karbon14
+Name[cs]=Exportní filtr do formátu WMF pro Karbon14
+Name[cy]=Hidlen Allforio WMF Karbon14
+Name[da]=Karbon14 WMF-eksportfilter
+Name[de]=Karbon14 WMF-Exportfilter
+Name[el]=Φίλτρο εξαγωγής WMF του Karbon14
+Name[eo]=Karbon14-WMF-eksportfiltrilo
+Name[es]=Filtro de exportación WMF de Karbon14
+Name[et]=Karbon14 WMF-i ekspordifilter
+Name[eu]=Karbon14-en WMF esportaziorako iragazkia
+Name[fa]=پالایۀ صادرات Karbon14 WMF
+Name[fi]=Karbon14 WMF -vientisuodin
+Name[fr]=Filtre d'exportation WMF de Karbon 14
+Name[fy]=WMF-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála WMF Karbon14
+Name[gl]=Filtro de Exportación de WMF para Karbon14
+Name[he]=מסנן ייצוא מ־Karbon14 ל־WMF
+Name[hr]=Karbon14 WMF filtar izvoza
+Name[hu]=Karbon14 WMF exportszűrő
+Name[is]=Karbon14 WMF útflutningssía
+Name[it]=Filtro di esportazione WMF per Karbon14
+Name[ja]=Karbon14 WMF エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ WMF សម្រាប់ Karbon14
+Name[lt]=Karbon14 WMF eksportavimo filtras
+Name[lv]=Karbon14 WMF eksporta filtrs
+Name[ms]=Penapis Eksport Karbon14 WMF
+Name[nb]=WMF-eksportfilter for Karbon14
+Name[nds]=WMF-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ डब्लुएमएफ निर्यात फिल्टर
+Name[nl]=WMF-exportfilter voor Karbon14
+Name[nn]=WMF-eksportfilter for Karbon14
+Name[pl]=Filtr eksportu do formatu WMF z Karbon14
+Name[pt]=Filtro de Exportação de WMF para o Karbon14
+Name[pt_BR]=Filtro de Exportação WMF do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru WMF
+Name[ru]=Фильтр экспорта рисунков Karbon14 в WMF
+Name[se]=Karbon14:a WMF-olggosfievrridansilli
+Name[sk]=WFM filter pre export z Karbon14
+Name[sl]=Izvozni filter WMF za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у WMF
+Name[sr@Latn]=Karbon14-ov filter za izvoz u WMF
+Name[sv]=Karbon14 WMF-exportfilter
+Name[ta]=Karbon 14 WNF ஏற்றுமதி வடிகட்டி
+Name[tg]=Karbon14 WMF Филтри Содирот
+Name[tr]=Karbon14 WMF Aktarma Filtresi
+Name[uk]=Фільтр експорту WMF для Karbon14
+Name[uz]=Karbon14 WMF eksport filteri
+Name[uz@cyrillic]=Karbon14 WMF экспорт филтери
+Name[zh_CN]=Karbon14 WMF 导出过滤器
+Name[zh_TW]=Karbon14 WMF 匯出過濾程式
+ServiceTypes=KOfficeFilter
+Type=Service
+X-KDE-Export=image/x-wmf
+X-KDE-Import=application/x-karbon
+X-KDE-Weight=1
+X-KDE-Library=libwmfexport
+
diff --git a/filters/karbon/wmf/karbon_wmf_import.desktop b/filters/karbon/wmf/karbon_wmf_import.desktop
new file mode 100644
index 00000000..d1711ff9
--- /dev/null
+++ b/filters/karbon/wmf/karbon_wmf_import.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon WMF Import Filter
+Name[af]=Karbon Wmf In voer Filter
+Name[ar]=مِرْشَح استيراد WMF لدى Karbon
+Name[bg]=Филтър за импортиране от WMF в Karbon
+Name[br]=Sil enporzh WMF evit Karbon
+Name[ca]=Filtre d'importació WMF per a Karbon
+Name[cs]=Importní filtr WMF pro Karbon14
+Name[cy]=Hidlen Fewnforio WMF Karbon
+Name[da]=Karbon WMF-importfilter
+Name[de]=Karbon14 WMF-Importfilter
+Name[el]=Φίλτρο εισαγωγής WMF του Karbon
+Name[eo]=Karbon-WMF-importfiltrilo
+Name[es]=Filtro de importación WMF de Karbon
+Name[et]=Karboni WMF-i impordifilter
+Name[eu]=Karbon-en WMF inportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon WMF
+Name[fi]=Karbon WMF- tuontisuodin
+Name[fr]=Filtre d'importation WMF de Karbon 14
+Name[fy]=WMF-Ymportfilter foar Karbon
+Name[ga]=Scagaire Iompórtála Karbon WMF
+Name[gl]=Filtro de Importación de WMF para Karbon14
+Name[he]=מסנן ייבוא מ־WMF ל־Karbon
+Name[hr]=Kontour WMF filtar uvoza
+Name[hu]=Karbon WMF importszűrő
+Name[is]=Karbon WMF innflutningssía
+Name[it]=Filtro di importazione WMF per Karbon
+Name[ja]=Karbon WMF インポートフィルタ
+Name[km]=តម្រង​នាំចូល WMF សម្រាប់ Karbon
+Name[lo]=ຕົວຕອງການນຳເຂົ້າ WMF ຂອງ Karbon
+Name[lt]=Karbon WMF importavimo filtras
+Name[lv]=Karbon WMF importa filtrs
+Name[ms]=Penapis Import Karbon WMF
+Name[mt]=Filtru għall-importazzjoni ta' WMF ġo Karbon14
+Name[nb]=WMF-importfilter for Karbon
+Name[nds]=WMF-Importfilter för Karbon
+Name[ne]=कार्बन डब्लुएमएफ निर्यात फिल्टर
+Name[nl]=WMF-importfilter voor Karbon
+Name[nn]=WMF-importfilter for Karbon14
+Name[pl]=Filtr importu formatu WMF do Karbon
+Name[pt]=Filtro de Importação de WMF para o Karbon14
+Name[pt_BR]=Filtro de Importação WMF do Karbon
+Name[ro]=Filtru importare Karbon14 pentru WMF
+Name[ru]=Фильтр импорта рисунков WMF в Karbon
+Name[se]=Karbon:a WMF-sisafievrridansilli
+Name[sk]=WMF filter pre import pre Karbon
+Name[sl]=Uvozni filter WMF za Karbon
+Name[sr]=Karbon-ов филтер за увоз из WMF-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz WMF-a
+Name[sv]=Karbon WMF-importfilter
+Name[ta]=Karbon wmf இறக்குமதி வடிகட்டி
+Name[tg]=Karbon WMF IФилтри Воридот
+Name[th]=ตัวกรองการนำเข้า WMF ของ Karbon
+Name[tr]=Karbon WMF Alma Filtresi
+Name[uk]=Фільтр імпорту WMF для Karbon
+Name[uz]=Karbon WMF import filteri
+Name[uz@cyrillic]=Karbon WMF импорт филтери
+Name[xh]=Isihluzi Sokurhweba se Karbon WMF
+Name[zh_CN]=Karbon WMF 导入过滤器
+Name[zh_TW]=Karbon WMF 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=image/x-wmf
+X-KDE-Weight=1
+X-KDE-Library=libwmfimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/wmf/wmfexport.cc b/filters/karbon/wmf/wmfexport.cc
new file mode 100644
index 00000000..5f1e94d7
--- /dev/null
+++ b/filters/karbon/wmf/wmfexport.cc
@@ -0,0 +1,263 @@
+/* This file is part of the KDE project
+ * Copyright (c) 2003 thierry lorthiois (lorthioist@wanadoo.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+#include <qdom.h>
+#include <qcstring.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+#include <KoStoreDevice.h>
+#include "vdocument.h"
+#include "vcolor.h"
+#include "vcomposite.h"
+#include "vdashpattern.h"
+#include "vdocument.h"
+#include "vlayer.h"
+#include "vpath.h"
+#include "vsegment.h"
+#include "vfill.h"
+#include "vstroke.h"
+#include "vtext.h"
+#include "vflattencmd.h"
+
+#include "wmfexport.h"
+#include "kowmfwrite.h"
+
+/*
+TODO: bs.wmf stroke in red with MSword and in brown with Kword ??
+*/
+
+typedef KGenericFactory<WmfExport, KoFilter> WmfExportFactory;
+K_EXPORT_COMPONENT_FACTORY( libwmfexport, WmfExportFactory( "kofficefilters" ) )
+
+
+WmfExport::WmfExport( KoFilter *, const char *, const QStringList&) :
+ KoFilter()
+{
+}
+
+WmfExport::~WmfExport()
+{
+}
+
+KoFilter::ConversionStatus WmfExport::convert( const QCString& from, const QCString& to )
+{
+ if( to != "image/x-wmf" || from != "application/x-karbon" ) {
+ return KoFilter::NotImplemented;
+ }
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+
+ if( !storeIn ) {
+ return KoFilter::StupidError;
+ }
+
+ // open Placeable Wmf file
+ mWmf = new KoWmfWrite( m_chain->outputFile() );
+ if( !mWmf->begin() ) {
+ delete mWmf;
+ return KoFilter::WrongFormat;
+ }
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ // Load the document.
+ mDoc = new VDocument;
+ mDoc->load( docNode );
+
+ // Process the document.
+ mDoc->accept( *this );
+
+ mWmf->end();
+
+ delete mWmf;
+ delete mDoc;
+
+ return KoFilter::OK;
+}
+
+
+void WmfExport::visitVDocument( VDocument& document ) {
+ int width;
+ int height;
+
+ mDoc = &document;
+ mListPa.setAutoDelete( true );
+
+ // resolution
+ mDpi = 1000;
+ width = (int)(POINT_TO_INCH( document.width() ) * mDpi);
+ height = (int)(POINT_TO_INCH( document.height() ) * mDpi);
+
+ mWmf->setDefaultDpi( mDpi );
+ mWmf->setWindow( 0, 0, width, height );
+
+ if ( (document.width() != 0) && (document.height() != 0) ) {
+ mScaleX = (double)width / document.width();
+ mScaleY = (double)height / document.height();
+ }
+
+ // Export layers.
+ VVisitor::visitVDocument( document );
+
+}
+
+
+void WmfExport::visitVPath( VPath& composite ) {
+ QPen pen;
+ QBrush brush;
+
+ getPen( pen, composite.stroke() );
+ getBrush( brush, composite.fill() );
+
+ VVisitor::visitVPath( composite );
+
+ if ( mListPa.count() > 0 ) {
+ mWmf->setPen( pen );
+ if( (brush.style() == Qt::NoBrush)
+ && (mListPa.count() == 1) ) {
+ mWmf->drawPolyline( *mListPa.first() );
+ }
+ else {
+ mWmf->setBrush( brush );
+
+ if ( mListPa.count() == 1 ) {
+ mWmf->drawPolygon( *mListPa.first() );
+ }
+ else {
+ // combined path
+ mWmf->drawPolyPolygon( mListPa );
+ }
+ }
+ }
+ mListPa.clear();
+}
+
+
+// Export segment.
+void WmfExport::visitVSubpath( VSubpath& path ) {
+ VSubpath *newPath;
+ VSubpathIterator itr( path );
+ VFlattenCmd cmd( 0L, INCH_TO_POINT(0.3 / (double)mDpi) );
+ QPointArray *pa = new QPointArray( path.count() );
+ int nbrPoint=0; // number of points in the path
+
+ for( ; itr.current(); ++itr ) {
+ VSegment *segment= itr.current();
+ if (segment->isCurve()) {
+ newPath = new VSubpath( mDoc );
+
+ // newPath duplicate the list of curve
+ newPath->moveTo( itr.current()->prev()->knot() );
+ newPath->append( itr.current()->clone() );
+ while( itr.current()->next() ) {
+ if ( itr.current()->next()->isCurve() ) {
+ newPath->append( itr.current()->next()->clone() );
+ }
+ else {
+ break;
+ }
+ ++itr;
+ }
+
+ // flatten the curve
+ cmd.visit( *newPath );
+
+ // adjust the number of points
+ pa->resize( pa->size() + newPath->count() - 2 );
+
+ // Ommit the first segment and insert points
+ newPath->first();
+ while( newPath->next() ) {
+ pa->setPoint( nbrPoint++, coordX( newPath->current()->knot().x() ),
+ coordY( newPath->current()->knot().y() ) );
+ }
+ delete newPath;
+ } else if (segment->isLine()) {
+ pa->setPoint( nbrPoint++, coordX( itr.current()->knot().x() ),
+ coordY( itr.current()->knot().y() ) );
+ } else if (segment->isBegin()) {
+ // start a new polygon
+ pa->setPoint( nbrPoint++, coordX( itr.current()->knot().x() ),
+ coordY( itr.current()->knot().y() ) );
+ }
+ }
+
+ // adjust the number of points
+ if ( nbrPoint > 1 ) {
+ pa->resize( nbrPoint );
+ mListPa.append( pa );
+ }
+ else {
+ delete pa;
+ // TODO: check why we have empty path
+ kdDebug() << "WmfExport::visitVSubpath : Empty path ?" << endl;
+ }
+}
+
+
+void WmfExport::visitVText( VText& text ) {
+ // TODO: export text
+ visitVSubpath( text.basePath() );
+}
+
+
+void WmfExport::getBrush( QBrush& brush, const VFill *fill ) {
+ if( (fill->type() == VFill::solid) || (fill->type() == VFill::grad)
+ || (fill->type() == VFill::patt) ) {
+ if ( fill->color().opacity() < 0.1 ) {
+ brush.setStyle( Qt::NoBrush );
+ }
+ else {
+ brush.setStyle( Qt::SolidPattern );
+ brush.setColor( fill->color() );
+ }
+ }
+ else {
+ brush.setStyle( Qt::NoBrush );
+ }
+}
+
+
+void WmfExport::getPen( QPen& pen, const VStroke *stroke ) {
+ if( (stroke->type() == VStroke::solid) || (stroke->type() == VStroke::grad)
+ || (stroke->type() == VStroke::patt) ) {
+ // TODO : Dash pattern.
+
+ if ( stroke->lineCap() == VStroke::capRound ) {
+ pen.setCapStyle( Qt::RoundCap );
+ }
+ else {
+ pen.setCapStyle( Qt::SquareCap );
+ }
+ pen.setStyle( Qt::SolidLine );
+ pen.setColor( stroke->color() );
+ pen.setWidth( coordX( stroke->lineWidth() ) );
+ }
+ else {
+ pen.setStyle( Qt::NoPen );
+ }
+}
+
+
+#include <wmfexport.moc>
+
diff --git a/filters/karbon/wmf/wmfexport.h b/filters/karbon/wmf/wmfexport.h
new file mode 100644
index 00000000..8f107ee0
--- /dev/null
+++ b/filters/karbon/wmf/wmfexport.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project
+ * Copyright (c) 2003 thierry lorthiois (lorthioist@wanadoo.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef WMFEXPORT_H
+#define WMFEXPORT_H
+
+#include <qpen.h>
+#include <qbrush.h>
+#include <qptrlist.h>
+#include <qpointarray.h>
+#include <KoFilter.h>
+#include "vvisitor.h"
+
+class KoWmfWrite;
+class VPath;
+class VDocument;
+class VSubpath;
+class VText;
+
+class WmfExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ WmfExport( KoFilter *parent, const char *name, const QStringList&);
+ virtual ~WmfExport();
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+private:
+ void visitVPath( VPath& composite );
+ void visitVDocument( VDocument& document );
+ void visitVSubpath( VSubpath& path );
+ void visitVText( VText& text );
+ void getBrush( QBrush& brush, const VFill *fill );
+ void getPen( QPen& pen, const VStroke *stroke );
+
+ // coordinate transformation
+ // translate origin from (left,bottom) to (left,top) -> scale to wmf size
+ // Wmf origin is (left,top) corner
+ // Karbon origin is (left,bottom) corner
+ int coordX( double left )
+ { return (int)(left * mScaleX); }
+ int coordY( double top )
+ { return (int)((mDoc->height() - top) * mScaleY); }
+
+private:
+ KoWmfWrite *mWmf;
+ VDocument *mDoc;
+ int mDpi;
+ double mScaleX;
+ double mScaleY;
+ QPtrList<QPointArray> mListPa;
+};
+
+#endif
diff --git a/filters/karbon/wmf/wmfimport.cc b/filters/karbon/wmf/wmfimport.cc
new file mode 100644
index 00000000..eadad26b
--- /dev/null
+++ b/filters/karbon/wmf/wmfimport.cc
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#include <config.h>
+#include <qdom.h>
+#include <qcstring.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <KoFilterChain.h>
+#include <KoStoreDevice.h>
+#include <core/vdocument.h>
+
+#include "wmfimport.h"
+#include "wmfimportparser.h"
+
+typedef KGenericFactory<WMFImport, KoFilter> WMFImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libwmfimport, WMFImportFactory( "kofficefilters" ) )
+
+
+WMFImport::WMFImport( KoFilter *, const char *, const QStringList&) :
+ KoFilter()
+{
+}
+
+WMFImport::~WMFImport()
+{
+}
+
+KoFilter::ConversionStatus WMFImport::convert( const QCString& from, const QCString& to )
+{
+ if( to != "application/x-karbon" || from != "image/x-wmf" )
+ return KoFilter::NotImplemented;
+
+ WMFImportParser wmfParser;
+ if( !wmfParser.load( m_chain->inputFile() ) ) {
+ return KoFilter::WrongFormat;
+ }
+
+ // Do the conversion!
+ VDocument document;
+ if (!wmfParser.play( document )) {
+ return KoFilter::WrongFormat;
+ }
+
+ KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
+ if( !out ) {
+ kdError(3800) << "Unable to open output file!" << endl;
+ return KoFilter::StorageCreationError;
+ }
+ QDomDocument outdoc = document.saveXML();
+ QCString content = outdoc.toCString();
+ // kdDebug() << " content : " << content << endl;
+ out->writeBlock( content , content.length() );
+
+ return KoFilter::OK;
+}
+
+
+#include <wmfimport.moc>
diff --git a/filters/karbon/wmf/wmfimport.h b/filters/karbon/wmf/wmfimport.h
new file mode 100644
index 00000000..e1290422
--- /dev/null
+++ b/filters/karbon/wmf/wmfimport.h
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>.
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#ifndef WMFIMPORT_H
+#define WMFIMPORT_H
+
+#include <KoFilter.h>
+#include <KoStore.h>
+
+
+class WMFImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ WMFImport( KoFilter *parent, const char *name, const QStringList&);
+ virtual ~WMFImport();
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+};
+
+#endif
diff --git a/filters/karbon/wmf/wmfimportparser.cc b/filters/karbon/wmf/wmfimportparser.cc
new file mode 100644
index 00000000..2eb380a4
--- /dev/null
+++ b/filters/karbon/wmf/wmfimportparser.cc
@@ -0,0 +1,371 @@
+/* This file is part of the KDE project
+ * Copyright (c) 2003 thierry lorthiois (lorthioist@wanadoo.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+#include <shapes/vellipse.h>
+#include <shapes/vrectangle.h>
+#include <shapes/vpolygon.h>
+#include <core/vstroke.h>
+#include <core/vfill.h>
+
+#include "wmfimportparser.h"
+
+/*
+bug : see motar.wmf
+*/
+
+WMFImportParser::WMFImportParser() : KoWmfRead() {
+}
+
+
+bool WMFImportParser::play( VDocument& doc )
+{
+ mDoc = &doc;
+ mScaleX = mScaleY = 1;
+
+ // Play the wmf file
+ return KoWmfRead::play( );
+}
+
+
+//-----------------------------------------------------------------------------
+// Virtual Painter
+
+bool WMFImportParser::begin() {
+ QRect bounding = boundingRect();
+
+ mBackgroundMode = Qt::TransparentMode;
+ mCurrentOrg.setX( bounding.left() );
+ mCurrentOrg.setY( bounding.top() );
+
+ if ( isStandard() ) {
+ mDoc->setUnit( KoUnit::U_PT );
+ mDoc->setWidth( bounding.width() );
+ mDoc->setHeight( bounding.height() );
+ }
+ else {
+ // Placeable Wmf store the boundingRect() in pixel and the default DPI
+ // The placeable format doesn't have informations on witch Unit to use
+ // so we choose millimeters by default
+ mDoc->setUnit( KoUnit::U_MM );
+ mDoc->setWidth( INCH_TO_POINT( (double)bounding.width() / defaultDpi() ) );
+ mDoc->setHeight( INCH_TO_POINT( (double)bounding.height() / defaultDpi() ) );
+ }
+ if ( (bounding.width() != 0) && (bounding.height() != 0) ) {
+ mScaleX = mDoc->width() / (double)bounding.width();
+ mScaleY = mDoc->height() / (double)bounding.height();
+ }
+ return true;
+}
+
+
+bool WMFImportParser::end() {
+ return true;
+}
+
+
+void WMFImportParser::save() {
+}
+
+
+void WMFImportParser::restore() {
+}
+
+
+void WMFImportParser::setFont( const QFont & ) {
+}
+
+
+void WMFImportParser::setPen( const QPen &pen ) {
+ mPen = pen;
+}
+
+
+const QPen &WMFImportParser::pen() const {
+ return mPen;
+}
+
+
+void WMFImportParser::setBrush( const QBrush &brush ) {
+ mBrush = brush;
+}
+
+
+void WMFImportParser::setBackgroundColor( const QColor &c ) {
+ mBackgroundColor = c;
+}
+
+
+void WMFImportParser::setBackgroundMode( Qt::BGMode mode ) {
+ mBackgroundMode = mode;
+}
+
+
+void WMFImportParser::setRasterOp( Qt::RasterOp ) {
+}
+
+
+void WMFImportParser::setWindowOrg( int left, int top ) {
+ mCurrentOrg.setX( left );
+ mCurrentOrg.setY( top );
+}
+
+
+void WMFImportParser::setWindowExt( int width, int height ) {
+ // the wmf file can change width/height during the drawing
+ if ( (width != 0) && (height != 0) ) {
+ mScaleX = mDoc->width() / (double)width;
+ mScaleY = mDoc->height() / (double)height;
+ }
+}
+
+
+void WMFImportParser::setWorldMatrix( const QWMatrix &, bool ) {
+}
+
+
+void WMFImportParser::setClipRegion( const QRegion & ) {
+}
+
+
+QRegion WMFImportParser::clipRegion() {
+ return mClippingRegion;
+}
+
+
+void WMFImportParser::moveTo( int left, int top ) {
+ mCurrentPoint.setX( left );
+ mCurrentPoint.setY( top );
+}
+
+
+void WMFImportParser::lineTo( int left, int top ) {
+ VPath *line = new VPath( mDoc );
+ line->moveTo( KoPoint( coordX(mCurrentPoint.x()), coordY(mCurrentPoint.y()) ) );
+ line->lineTo( KoPoint( coordX(left), coordY(top) ) );
+ appendPen( *line );
+
+ mDoc->append( line );
+ mCurrentPoint.setX( left );
+ mCurrentPoint.setY( top );
+}
+
+
+void WMFImportParser::drawRect( int left, int top, int width, int height ) {
+ VRectangle *rectangle;
+
+ rectangle = new VRectangle( mDoc, KoPoint( coordX(left), coordY(top) ), scaleW(width), scaleH(height), 0 );
+ appendPen( *rectangle );
+ appendBrush( *rectangle );
+
+ mDoc->append( rectangle );
+}
+
+
+void WMFImportParser::drawRoundRect( int left, int top, int width, int height, int roudw, int ) {
+ VRectangle *rectangle;
+
+ // TODO : round rectangle
+ rectangle = new VRectangle( mDoc, KoPoint( coordX(left), coordY(top) ), scaleW(width), scaleH(height), roudw );
+ appendPen( *rectangle );
+ appendBrush( *rectangle );
+
+ mDoc->append( rectangle );
+}
+
+
+void WMFImportParser::drawEllipse( int left, int top, int width, int height ) {
+ VEllipse *ellipse;
+
+ ellipse = new VEllipse( mDoc, KoPoint( coordX(left), coordY(top+height) ), scaleW(width), scaleH(height) );
+ appendPen( *ellipse );
+ appendBrush( *ellipse );
+
+ mDoc->append( ellipse );
+}
+
+
+void WMFImportParser::drawArc( int x, int y, int w, int h, int aStart, int aLen ) {
+ double start = (aStart * 180) / 2880.0;
+ double end = (aLen * 180) / 2880.0;
+ end += start;
+ VEllipse::VEllipseType type = VEllipse::arc;
+
+ VEllipse *arc = new VEllipse( mDoc, KoPoint( coordX(x), coordY(y+h) ), scaleW(w), scaleH(h), type, start, end );
+ appendPen( *arc );
+
+ mDoc->append( arc );
+}
+
+
+void WMFImportParser::drawPie( int x, int y, int w, int h, int aStart, int aLen ) {
+ double start = (aStart * 180) / 2880.0;
+ double end = (aLen * 180) / 2880.0;
+ end += start;
+ VEllipse::VEllipseType type = VEllipse::cut;
+
+ VEllipse *arc = new VEllipse( mDoc, KoPoint( coordX(x), coordY(y+h) ), scaleW(w), scaleH(h), type, start, end );
+ appendPen( *arc );
+ appendBrush( *arc );
+
+ mDoc->append( arc );
+}
+
+
+void WMFImportParser::drawChord( int x, int y, int w, int h, int aStart, int aLen ) {
+ double start = (aStart * 180) / 2880.0;
+ double end = (aLen * 180) / 2880.0;
+ end += start;
+ VEllipse::VEllipseType type = VEllipse::section;
+
+ VEllipse *arc = new VEllipse( mDoc, KoPoint( coordX(x), coordY(y+h) ), scaleW(w), scaleH(h), type, start, end );
+ appendPen( *arc );
+ appendBrush( *arc );
+
+ mDoc->append( arc );
+}
+
+
+void WMFImportParser::drawPolyline( const QPointArray &pa ) {
+ VPath *polyline = new VPath( mDoc );
+ appendPen( *polyline );
+ appendPoints( *polyline, pa );
+
+ mDoc->append( polyline );
+}
+
+
+void WMFImportParser::drawPolygon( const QPointArray &pa, bool ) {
+ VPath *polygon = new VPath( mDoc );
+ appendPen( *polygon );
+ appendBrush( *polygon );
+ appendPoints( *polygon, pa );
+
+ polygon->close();
+ mDoc->append( polygon );
+}
+
+
+void WMFImportParser::drawPolyPolygon( QPtrList<QPointArray>& listPa, bool ) {
+ VPath *path = new VPath( mDoc );
+
+ if ( listPa.count() > 0 ) {
+ appendPen( *path );
+ appendBrush( *path );
+ appendPoints( *path, *listPa.first() );
+ path->close();
+
+ while ( listPa.next() ) {
+ VPath *newPath = new VPath( mDoc );
+ appendPoints( *newPath, *listPa.current() );
+ newPath->close();
+ path->combine( *newPath );
+ }
+
+ mDoc->append( path );
+ }
+}
+
+
+void WMFImportParser::drawImage( int , int , const QImage &, int , int , int , int ) {}
+
+
+void WMFImportParser::drawText( int , int , int , int , int , const QString& , double ) {}
+
+
+//-----------------------------------------------------------------------------
+// Utilities
+
+void WMFImportParser::appendPen( VObject& obj )
+{
+ VStroke stroke( mDoc );
+ stroke.setLineCap( VStroke::capRound );
+
+ if ( mPen.style() == Qt::NoPen ) {
+ stroke.setType( VStroke::none );
+ }
+ else {
+ QValueList<float> dashes;
+ stroke.setType( VStroke::solid );
+ switch ( mPen.style() ) {
+ case Qt::DashLine :
+ stroke.dashPattern().setArray( dashes << MM_TO_POINT(3) << MM_TO_POINT(2) );
+ break;
+ case Qt::DotLine :
+ stroke.dashPattern().setArray( dashes << MM_TO_POINT(1) << MM_TO_POINT(1) );
+ break;
+ case Qt::DashDotLine :
+ stroke.dashPattern().setArray( dashes << MM_TO_POINT(3) << MM_TO_POINT(1) << MM_TO_POINT(1) << MM_TO_POINT(1) );
+ break;
+ case Qt::DashDotDotLine :
+ stroke.dashPattern().setArray( dashes << MM_TO_POINT(3) << MM_TO_POINT(1) << MM_TO_POINT(1) << MM_TO_POINT(1) << MM_TO_POINT(1) << MM_TO_POINT(1) );
+ break;
+ default:
+ break;
+ }
+ }
+ stroke.setColor( mPen.color() );
+ double width = mPen.width() * mScaleX;
+ stroke.setLineWidth( ((width < 0.99) ? 1 : width) );
+ obj.setStroke( stroke );
+}
+
+
+void WMFImportParser::appendBrush( VObject& obj )
+{
+ VFill fill( mBackgroundColor );
+ fill.setColor( mBrush.color() );
+
+ switch ( mBrush.style() ) {
+ case Qt::NoBrush :
+ fill.setType( VFill::none );
+ break;
+ case Qt::SolidPattern :
+ fill.setType( VFill::solid );
+ break;
+ case Qt::CustomPattern :
+ // TODO: bitmap pattern brush
+ fill.setType( VFill::solid );
+ //fill.pattern().
+ break;
+ default :
+ // TODO: pattern brush
+ if ( mBackgroundMode == Qt::OpaqueMode ) {
+ fill.setColor( mBackgroundColor );
+ fill.setType( VFill::solid );
+ }
+ else {
+ fill.setType( VFill::none );
+ }
+ break;
+ }
+ obj.setFill( fill );
+}
+
+
+void WMFImportParser::appendPoints(VPath &path, const QPointArray& pa)
+{
+ // list of point array
+ if ( pa.size() > 0 ) {
+ path.moveTo( KoPoint( coordX(pa.point(0).x()), coordY(pa.point(0).y()) ) );
+ }
+ for ( uint i=1 ; i < pa.size() ; i++ ) {
+ path.lineTo( KoPoint( coordX(pa.point(i).x()), coordY(pa.point(i).y()) ) );
+ }
+}
+
diff --git a/filters/karbon/wmf/wmfimportparser.h b/filters/karbon/wmf/wmfimportparser.h
new file mode 100644
index 00000000..fcb1fbe2
--- /dev/null
+++ b/filters/karbon/wmf/wmfimportparser.h
@@ -0,0 +1,141 @@
+/* This file is part of the KDE project
+ * Copyright (c) 2003 thierry lorthiois (lorthioist@wanadoo.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#ifndef _WMFIMPORTPARSER_H_
+#define _WMFIMPORTPARSER_H_
+
+#include <qpainter.h>
+#include <qdom.h>
+#include <core/vdocument.h>
+#include <core/vcomposite.h>
+#include <kowmfread.h>
+
+
+/**
+ * WMFImportParser inherit KoWmfRead
+ * and translate WMF functions
+ *
+ */
+
+class WMFImportParser : public KoWmfRead
+{
+public:
+ WMFImportParser();
+ ~WMFImportParser() { }
+
+ /**
+ * play WMF file on a VDocument. Return true on success.
+ */
+ bool play( VDocument& doc );
+
+
+private:
+ // -------------------------------------------------------------------------
+ // A virtual QPainter
+ bool begin();
+ bool end();
+ void save();
+ void restore();
+
+ // Drawing tools
+ void setFont( const QFont &font );
+ // the pen : the width of the pen is in logical coordinate
+ void setPen( const QPen &pen );
+ const QPen &pen() const;
+ void setBrush( const QBrush &brush );
+
+ // Drawing attributes/modes
+ void setBackgroundColor( const QColor &c );
+ void setBackgroundMode( Qt::BGMode mode );
+ void setRasterOp( Qt::RasterOp op );
+
+ /**
+ * Change logical Coordinate
+ * some wmf files call those functions several times in the middle of a drawing
+ * others wmf files doesn't call setWindow* at all
+ * negative width and height are possible
+ */
+ void setWindowOrg( int left, int top );
+ void setWindowExt( int width, int height );
+
+ // Clipping
+ // the 'CoordinateMode' is ommitted : always CoordPainter in wmf
+ // setClipRegion() is often used with save() and restore() => implement all or none
+ void setClipRegion( const QRegion &rec );
+ QRegion clipRegion();
+
+ // Graphics drawing functions
+ void moveTo( int x, int y );
+ void lineTo( int x, int y );
+ void drawRect( int x, int y, int w, int h );
+ void drawRoundRect( int x, int y, int w, int h, int = 25, int = 25 );
+ void drawEllipse( int x, int y, int w, int h );
+ void drawArc( int x, int y, int w, int h, int a, int alen );
+ void drawPie( int x, int y, int w, int h, int a, int alen );
+ void drawChord( int x, int y, int w, int h, int a, int alen );
+ void drawPolyline( const QPointArray &pa );
+ void drawPolygon( const QPointArray &pa, bool winding=FALSE );
+ /**
+ * drawPolyPolygon draw the XOR of a list of polygons
+ * listPa : list of polygons
+ */
+ void drawPolyPolygon( QPtrList<QPointArray>& listPa, bool winding=FALSE );
+ void drawImage( int x, int y, const QImage &, int sx = 0, int sy = 0, int sw = -1, int sh = -1 );
+
+ // Text drawing
+ // rotation = the degrees of rotation in counterclockwise
+ // not yet implemented in KWinMetaFile
+ void drawText( int x, int y, int w, int h, int flags, const QString &s, double rotation );
+
+ // matrix transformation : only used in some bitmap manipulation
+ void setWorldMatrix( const QWMatrix &, bool combine=FALSE );
+
+ //-----------------------------------------------------------------------------
+ // Utilities
+ // Add pen, brush and points to a path
+ void appendPen( VObject& obj );
+ void appendBrush( VObject& obj );
+ void appendPoints(VPath& path, const QPointArray& pa);
+ // coordinate transformation
+ // translate wmf to (0,0) -> scale to document size -> translate to karbon (0,0)
+ // Wmf origin is (left,top) corner
+ // Karbon origin is (left,bottom) corner
+ double coordX( int left )
+ { return ((double)(left - mCurrentOrg.x()) * mScaleX); }
+ double coordY( int top )
+ { return (mDoc->height() - ((double)(top - mCurrentOrg.y()) * mScaleY)); }
+ double scaleW( int width )
+ { return (width * mScaleX); }
+ double scaleH( int height )
+ { return (height * mScaleY); }
+
+private:
+ VDocument *mDoc;
+ QRegion mClippingRegion;
+ QPen mPen;
+ QBrush mBrush;
+ Qt::BGMode mBackgroundMode;
+ QColor mBackgroundColor;
+ // current origin of WMF logical coordinate
+ QPoint mCurrentOrg;
+ double mScaleX;
+ double mScaleY;
+ // current position in WMF coordinate (INT16)
+ QPoint mCurrentPoint;
+};
+
+#endif
diff --git a/filters/karbon/xaml/Makefile.am b/filters/karbon/xaml/Makefile.am
new file mode 100644
index 00000000..f7036ada
--- /dev/null
+++ b/filters/karbon/xaml/Makefile.am
@@ -0,0 +1,35 @@
+kde_module_LTLIBRARIES = libkarbonxamlexport.la libkarbonxamlimport.la
+
+libkarbonxamlexport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonxamlexport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+libkarbonxamlimport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonxamlimport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) \
+ $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/visitors \
+ $(all_includes)
+
+service_DATA = karbon_xaml_export.desktop karbon_xaml_import.desktop
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ xamlexport.h \
+ xamlimport.h
+
+libkarbonxamlexport_la_SOURCES = \
+ xamlexport.cc
+
+libkarbonxamlimport_la_SOURCES = \
+ xamlimport.cc
+
+METASOURCES = AUTO
+
diff --git a/filters/karbon/xaml/color.h b/filters/karbon/xaml/color.h
new file mode 100644
index 00000000..bfdc93c6
--- /dev/null
+++ b/filters/karbon/xaml/color.h
@@ -0,0 +1,306 @@
+
+#define TORGB( red, green, blue ) \
+{ \
+ r = red; \
+ b = blue; \
+ g = green; \
+}
+
+void keywordToRGB( QString rgbColor, int &r, int &g, int &b )
+{
+ if( rgbColor == "aliceblue" )
+ TORGB( 240, 248, 255)
+ else if( rgbColor == "antiquewhite" )
+ TORGB( 250, 235, 215)
+ else if( rgbColor == "aqua" )
+ TORGB( 0, 255, 255)
+ else if( rgbColor == "aquamarine" )
+ TORGB( 127, 255, 212 )
+ else if( rgbColor == "azure" )
+ TORGB( 240, 255, 255 )
+ else if( rgbColor == "beige" )
+ TORGB( 245, 245, 220 )
+ else if( rgbColor == "bisque" )
+ TORGB( 255, 228, 196 )
+ else if( rgbColor == "black" )
+ TORGB( 0, 0, 0 )
+ else if( rgbColor == "blanchedalmond" )
+ TORGB( 255, 235, 205 )
+ else if( rgbColor == "blue" )
+ TORGB( 0, 0, 255 )
+ else if( rgbColor == "blueviolet" )
+ TORGB( 138, 43, 226 )
+ else if( rgbColor == "brown" )
+ TORGB( 165, 42, 42 )
+ else if( rgbColor == "burlywood" )
+ TORGB( 222, 184, 135 )
+ else if( rgbColor == "cadetblue" )
+ TORGB( 95, 158, 160 )
+ else if( rgbColor == "chartreuse" )
+ TORGB( 127, 255, 0 )
+ else if( rgbColor == "chocolate" )
+ TORGB( 210, 105, 30 )
+ else if( rgbColor == "coral" )
+ TORGB( 255, 127, 80 )
+ else if( rgbColor == "cornflowerblue" )
+ TORGB( 100, 149, 237 )
+ else if( rgbColor == "cornsilk" )
+ TORGB( 255, 248, 220 )
+ else if( rgbColor == "crimson" )
+ TORGB( 220, 20, 60 )
+ else if( rgbColor == "cyan" )
+ TORGB( 0, 255, 255 )
+ else if( rgbColor == "darkblue" )
+ TORGB( 0, 0, 139 )
+ else if( rgbColor == "darkcyan" )
+ TORGB( 0, 139, 139 )
+ else if( rgbColor == "darkgoldenrod" )
+ TORGB( 184, 134, 11 )
+ else if( rgbColor == "darkgray" )
+ TORGB( 169, 169, 169 )
+ else if( rgbColor == "darkgrey" )
+ TORGB( 169, 169, 169 )
+ else if( rgbColor == "darkgreen" )
+ TORGB( 0, 100, 0 )
+ else if( rgbColor == "darkkhaki" )
+ TORGB( 189, 183, 107 )
+ else if( rgbColor == "darkmagenta" )
+ TORGB( 139, 0, 139 )
+ else if( rgbColor == "darkolivegreen" )
+ TORGB( 85, 107, 47 )
+ else if( rgbColor == "darkorange" )
+ TORGB( 255, 140, 0 )
+ else if( rgbColor == "darkorchid" )
+ TORGB( 153, 50, 204 )
+ else if( rgbColor == "darkred" )
+ TORGB( 139, 0, 0 )
+ else if( rgbColor == "darksalmon" )
+ TORGB( 233, 150, 122 )
+ else if( rgbColor == "darkseagreen" )
+ TORGB( 143, 188, 143 )
+ else if( rgbColor == "darkslateblue" )
+ TORGB( 72, 61, 139 )
+ else if( rgbColor == "darkslategray" )
+ TORGB( 47, 79, 79 )
+ else if( rgbColor == "darkslategrey" )
+ TORGB( 47, 79, 79 )
+ else if( rgbColor == "darkturquoise" )
+ TORGB( 0, 206, 209 )
+ else if( rgbColor == "darkviolet" )
+ TORGB( 148, 0, 211 )
+ else if( rgbColor == "deeppink" )
+ TORGB( 255, 20, 147 )
+ else if( rgbColor == "deepskyblue" )
+ TORGB( 0, 191, 255 )
+ else if( rgbColor == "dimgray" )
+ TORGB( 105, 105, 105 )
+ else if( rgbColor == "dimgrey" )
+ TORGB( 105, 105, 105 )
+ else if( rgbColor == "dodgerblue" )
+ TORGB( 30, 144, 255 )
+ else if( rgbColor == "firebrick" )
+ TORGB( 178, 34, 34 )
+ else if( rgbColor == "floralwhite" )
+ TORGB( 255, 250, 240 )
+ else if( rgbColor == "forestgreen" )
+ TORGB( 34, 139, 34 )
+ else if( rgbColor == "fuchsia" )
+ TORGB( 255, 0, 255 )
+ else if( rgbColor == "gainsboro" )
+ TORGB( 220, 220, 220 )
+ else if( rgbColor == "ghostwhite" )
+ TORGB( 248, 248, 255 )
+ else if( rgbColor == "gold" )
+ TORGB( 255, 215, 0 )
+ else if( rgbColor == "goldenrod" )
+ TORGB( 218, 165, 32 )
+ else if( rgbColor == "gray" )
+ TORGB( 128, 128, 128 )
+ else if( rgbColor == "grey" )
+ TORGB( 128, 128, 128 )
+ else if( rgbColor == "green" )
+ TORGB( 0, 128, 0 )
+ else if( rgbColor == "greenyellow" )
+ TORGB( 173, 255, 47 )
+ else if( rgbColor == "honeydew" )
+ TORGB( 240, 255, 240 )
+ else if( rgbColor == "hotpink" )
+ TORGB( 255, 105, 180 )
+ else if( rgbColor == "indianred" )
+ TORGB( 205, 92, 92 )
+ else if( rgbColor == "indigo" )
+ TORGB( 75, 0, 130 )
+ else if( rgbColor == "ivory" )
+ TORGB( 255, 255, 240 )
+ else if( rgbColor == "khaki" )
+ TORGB( 240, 230, 140 )
+ else if( rgbColor == "lavender" )
+ TORGB( 230, 230, 250 )
+ else if( rgbColor == "lavenderblush" )
+ TORGB( 255, 240, 245 )
+ else if( rgbColor == "lawngreen" )
+ TORGB( 124, 252, 0 )
+ else if( rgbColor == "lemonchiffon" )
+ TORGB( 255, 250, 205 )
+ else if( rgbColor == "lightblue" )
+ TORGB( 173, 216, 230 )
+ else if( rgbColor == "lightcoral" )
+ TORGB( 240, 128, 128 )
+ else if( rgbColor == "lightcyan" )
+ TORGB( 224, 255, 255 )
+ else if( rgbColor == "lightgoldenrodyellow" )
+ TORGB( 250, 250, 210 )
+ else if( rgbColor == "lightgray" )
+ TORGB( 211, 211, 211 )
+ else if( rgbColor == "lightgrey" )
+ TORGB( 211, 211, 211 )
+ else if( rgbColor == "lightgreen" )
+ TORGB( 144, 238, 144 )
+ else if( rgbColor == "lightpink" )
+ TORGB( 255, 182, 193 )
+ else if( rgbColor == "lightsalmon" )
+ TORGB( 255, 160, 122 )
+ else if( rgbColor == "lightseagreen" )
+ TORGB( 32, 178, 170 )
+ else if( rgbColor == "lightskyblue" )
+ TORGB( 135, 206, 250 )
+ else if( rgbColor == "lightslategray" )
+ TORGB( 119, 136, 153 )
+ else if( rgbColor == "lightslategrey" )
+ TORGB( 119, 136, 153 )
+ else if( rgbColor == "lightsteelblue" )
+ TORGB( 176, 196, 222 )
+ else if( rgbColor == "lightyellow" )
+ TORGB( 255, 255, 224 )
+ else if( rgbColor == "lime" )
+ TORGB( 0, 255, 0 )
+ else if( rgbColor == "limegreen" )
+ TORGB( 50, 205, 50 )
+ else if( rgbColor == "linen" )
+ TORGB( 250, 240, 230 )
+ else if( rgbColor == "magenta" )
+ TORGB( 255, 0, 255 )
+ else if( rgbColor == "maroon" )
+ TORGB( 128, 0, 0 )
+ else if( rgbColor == "mediumaquamarine" )
+ TORGB( 102, 205, 170 )
+ else if( rgbColor == "mediumblue" )
+ TORGB( 0, 0, 205 )
+ else if( rgbColor == "mediumorchid" )
+ TORGB( 186, 85, 211 )
+ else if( rgbColor == "mediumpurple" )
+ TORGB( 147, 112, 219 )
+ else if( rgbColor == "mediumseagreen" )
+ TORGB( 60, 179, 113 )
+ else if( rgbColor == "mediumslateblue" )
+ TORGB( 123, 104, 238 )
+ else if( rgbColor == "mediumspringgreen" )
+ TORGB( 0, 250, 154 )
+ else if( rgbColor == "mediumturquoise" )
+ TORGB( 72, 209, 204 )
+ else if( rgbColor == "mediumvioletred" )
+ TORGB( 199, 21, 133 )
+ else if( rgbColor == "midnightblue" )
+ TORGB( 25, 25, 112 )
+ else if( rgbColor == "mintcream" )
+ TORGB( 245, 255, 250 )
+ else if( rgbColor == "mistyrose" )
+ TORGB( 255, 228, 225 )
+ else if( rgbColor == "moccasin" )
+ TORGB( 255, 228, 181 )
+ else if( rgbColor == "navajowhite" )
+ TORGB( 255, 222, 173 )
+ else if( rgbColor == "navy" )
+ TORGB( 0, 0, 128 )
+ else if( rgbColor == "oldlace" )
+ TORGB( 253, 245, 230 )
+ else if( rgbColor == "olive" )
+ TORGB( 128, 128, 0 )
+ else if( rgbColor == "olivedrab" )
+ TORGB( 107, 142, 35 )
+ else if( rgbColor == "orange" )
+ TORGB( 255, 165, 0 )
+ else if( rgbColor == "orangered" )
+ TORGB( 255, 69, 0 )
+ else if( rgbColor == "orchid" )
+ TORGB( 218, 112, 214 )
+ else if( rgbColor == "palegoldenrod" )
+ TORGB( 238, 232, 170 )
+ else if( rgbColor == "palegreen" )
+ TORGB( 152, 251, 152 )
+ else if( rgbColor == "paleturquoise" )
+ TORGB( 175, 238, 238 )
+ else if( rgbColor == "palevioletred" )
+ TORGB( 219, 112, 147 )
+ else if( rgbColor == "papayawhip" )
+ TORGB( 255, 239, 213 )
+ else if( rgbColor == "peachpuff" )
+ TORGB( 255, 218, 185 )
+ else if( rgbColor == "peru" )
+ TORGB( 205, 133, 63 )
+ else if( rgbColor == "pink" )
+ TORGB( 255, 192, 203 )
+ else if( rgbColor == "plum" )
+ TORGB( 221, 160, 221 )
+ else if( rgbColor == "powderblue" )
+ TORGB( 176, 224, 230 )
+ else if( rgbColor == "purple" )
+ TORGB( 128, 0, 128 )
+ else if( rgbColor == "red" )
+ TORGB( 255, 0, 0 )
+ else if( rgbColor == "rosybrown" )
+ TORGB( 188, 143, 143 )
+ else if( rgbColor == "royalblue" )
+ TORGB( 65, 105, 225 )
+ else if( rgbColor == "saddlebrown" )
+ TORGB( 139, 69, 19 )
+ else if( rgbColor == "salmon" )
+ TORGB( 250, 128, 114 )
+ else if( rgbColor == "sandybrown" )
+ TORGB( 244, 164, 96 )
+ else if( rgbColor == "seagreen" )
+ TORGB( 46, 139, 87 )
+ else if( rgbColor == "seashell" )
+ TORGB( 255, 245, 238 )
+ else if( rgbColor == "sienna" )
+ TORGB( 160, 82, 45 )
+ else if( rgbColor == "silver" )
+ TORGB( 192, 192, 192 )
+ else if( rgbColor == "skyblue" )
+ TORGB( 135, 206, 235 )
+ else if( rgbColor == "slateblue" )
+ TORGB( 106, 90, 205 )
+ else if( rgbColor == "slategray" )
+ TORGB( 112, 128, 144 )
+ else if( rgbColor == "slategrey" )
+ TORGB( 112, 128, 144 )
+ else if( rgbColor == "snow" )
+ TORGB( 255, 250, 250 )
+ else if( rgbColor == "springgreen" )
+ TORGB( 0, 255, 127 )
+ else if( rgbColor == "steelblue" )
+ TORGB( 70, 130, 180 )
+ else if( rgbColor == "tan" )
+ TORGB( 210, 180, 140 )
+ else if( rgbColor == "teal" )
+ TORGB( 0, 128, 128 )
+ else if( rgbColor == "thistle" )
+ TORGB( 216, 191, 216 )
+ else if( rgbColor == "tomato" )
+ TORGB( 255, 99, 71 )
+ else if( rgbColor == "turquoise" )
+ TORGB( 64, 224, 208 )
+ else if( rgbColor == "violet" )
+ TORGB( 238, 130, 238 )
+ else if( rgbColor == "wheat" )
+ TORGB( 245, 222, 179 )
+ else if( rgbColor == "white" )
+ TORGB( 255, 255, 255 )
+ else if( rgbColor == "whitesmoke" )
+ TORGB( 245, 245, 245 )
+ else if( rgbColor == "yellow" )
+ TORGB( 255, 255, 0 )
+ else if( rgbColor == "yellowgreen" )
+ TORGB( 154, 205, 50 )
+}
+
diff --git a/filters/karbon/xaml/karbon_xaml_export.desktop b/filters/karbon/xaml/karbon_xaml_export.desktop
new file mode 100644
index 00000000..082c29e8
--- /dev/null
+++ b/filters/karbon/xaml/karbon_xaml_export.desktop
@@ -0,0 +1,54 @@
+[Desktop Entry]
+Icon=
+Name=Karbon14 WVG Export Filter
+Name[ar]=مِرْشَح تصدير WVG لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в WVG
+Name[br]=Sil ezporzh WVG evit Karbon14
+Name[ca]=Filtre d'exportació WVG per a Karbon14
+Name[cy]=Hidlen Allforio WVG Karbon14
+Name[da]=Karbon14 WVG-eksportfilter
+Name[de]=Karbon14 WVG-Exportfilter
+Name[el]=Φίλτρο εξαγωγής SVG του Karbon14
+Name[eo]=Karbon14-WVG-eksportfiltrilo
+Name[es]=Filtro de exportación a WVG de Karbon14
+Name[et]=Karbon14 WVG ekspordifilter
+Name[fa]=پالایۀ صادرات Karbon14 WVG
+Name[fi]=Karbon14 WVG -vientisuodin
+Name[fr]=Filtre d'exportation WVG de Karbon 14
+Name[fy]=WVG-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála WVG Karbon14
+Name[gl]=Filtro de Exportación de WVG para Karbon14
+Name[he]=Karbon14 WVG מסנן יצוא
+Name[hr]=Karbon14 WVG filtar izvoza
+Name[hu]=Karbon14 WVG exportszűrő
+Name[is]=Karbon14 WVG útflutningssía
+Name[it]=Filtro di esportazione WVG per Karbon14
+Name[ja]=Karbon14 WVG エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ WVG សម្រាប់ Karbon14
+Name[lt]=Karbon14 WVG eksportavimo filtras
+Name[lv]=Karbon14 WVG eksporta filtrs
+Name[nb]=WVG-eksportfiler for Karbon14
+Name[nds]=WVG-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ डब्लुभीजी निर्यात फिल्टर
+Name[nl]= WVG-exportfilter voor Karbon14
+Name[pl]=Filtr eksportu do formatu WVG z Karbon14
+Name[pt]=Filtro de Exportação de WVG para o Karbon14
+Name[pt_BR]=Filtro de Exportação de WVG para o Karbon14
+Name[ru]=Фильтр экспорта рисунков Karbon в WVG
+Name[se]=Karbon14:a WVG-olggosfievrridansilli
+Name[sk]=WVG filter pre export z Karbon14
+Name[sl]=Izvozni filter WVG za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у WVG
+Name[sr@Latn]=Karbon14-ov filter za izvoz u WVG
+Name[sv]=Karbon14 WVG-exportfilter
+Name[uk]=Фільтр експорту WVG для Karbon14
+Name[uz]=Karbon14 WVG eksport filteri
+Name[uz@cyrillic]=Karbon14 WVG экспорт филтери
+Name[zh_CN]=Karbon14 WVG 导出过滤器
+Name[zh_TW]=Karbon14 WVG 匯出過濾程式
+ServiceTypes=KOfficeFilter
+Type=Service
+X-KDE-Export=image/wvg+xml
+X-KDE-Import=application/x-karbon
+X-KDE-Library=libkarbonxamlexport
+X-KDE-Weight=1
diff --git a/filters/karbon/xaml/karbon_xaml_import.desktop b/filters/karbon/xaml/karbon_xaml_import.desktop
new file mode 100644
index 00000000..6acd1f1f
--- /dev/null
+++ b/filters/karbon/xaml/karbon_xaml_import.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon XAML Import Filter
+Name[ar]=مِرْشَح استيراد XAML لدى Karbon
+Name[bg]=Филтър за импортиране от XAML в Karbon
+Name[br]=Sil enporzh XAML evit Karbon
+Name[ca]=Filtre d'importació XAML per a Karbon
+Name[cy]=Hidlen Fewnforio XAML Karbon
+Name[da]=Karbon XAML-importfilter
+Name[de]=Karbon14 XAML-Importfilter
+Name[el]=Φίλτρο εισαγωγής XAML του Karbon
+Name[eo]=Karbon-XAML-importfiltrilo
+Name[es]=Filtro de importación a XAML de Karbon
+Name[et]=Karboni XAML-i impordifilter
+Name[fa]=پالایۀ واردات Karbon XAML
+Name[fi]=Karbon XAML -tuontisuodin
+Name[fr]=Filtre d'importation XAML de Karbon 14
+Name[fy]=XAML-tmportfilter foar Karbon
+Name[ga]=Scagaire Iompórtála Karbon XAML
+Name[gl]=Filtro de Importación de XAML para Karbon
+Name[he]=Karbon XAML מסנן יבוא
+Name[hr]=Karbon XAML filtar uvoza
+Name[hu]=Karbon XAML importszűrő
+Name[is]=Karbon XAML innflutningssía
+Name[it]=Filtro di importazione XAML per Karbon
+Name[ja]=Karbon XAML インポートフィルタ
+Name[km]=តម្រង​នាំចូល XAML សម្រាប់ Karbon
+Name[lt]=Karbon XAML importavimo filtras
+Name[lv]=Karbon XAML importa filtrs
+Name[nb]=XAML-importfilter for Karbon
+Name[nds]=XAML-Importfilter för Karbon
+Name[ne]=कार्बन एक्सएएमएल निर्यात फिल्टर
+Name[nl]=XAML-importfilter voor Karbon
+Name[pl]=Filtr importu formatu XAML do Karbon
+Name[pt]=Filtro de Importação de XAML para o Karbon
+Name[pt_BR]=Filtro de Importação de XAML para o Karbon
+Name[ru]=Фильтр импорта файлов XAML в Karbon
+Name[se]=Karbon:a XAML-sisafievrridansilli
+Name[sk]=XAML importný filter pre Karbon
+Name[sl]=Uvozni filter XAML za Karbon
+Name[sr]=Karbon-ов филтер за увоз из XAML-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz XAML-a
+Name[sv]=Karbon XAML-importfilter
+Name[uk]=Фільтр імпорту XAML для Karbon
+Name[uz]=Karbon XAML import filteri
+Name[uz@cyrillic]=Karbon XAML импорт филтери
+Name[zh_CN]=Karbon XAML 导入过滤器
+Name[zh_TW]=Karbon XAML 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=image/wvg+xml
+X-KDE-Weight=1
+X-KDE-Library=libkarbonxamlimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/xaml/xamlexport.cc b/filters/karbon/xaml/xamlexport.cc
new file mode 100644
index 00000000..c4ccb467
--- /dev/null
+++ b/filters/karbon/xaml/xamlexport.cc
@@ -0,0 +1,371 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+// based on the SVG exporter. Not intended for public release
+// Microsoft WVG renamed to XAML Graphics. Worry about that later.
+
+#include <qcstring.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kgenericfactory.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include "xamlexport.h"
+#include "vcolor.h"
+#include "vcomposite.h"
+#include "vdashpattern.h"
+#include "vdocument.h"
+#include "vfill.h"
+#include "vgradient.h"
+#include "vgroup.h"
+#include "vlayer.h"
+#include "vpath.h"
+#include "vsegment.h"
+#include "vselection.h"
+#include "vstroke.h"
+//#include "vtext.h" // TODO Convert Text to Paths for basic export. Not our problem.
+// TODO inline Images?
+
+#include <kdebug.h>
+
+
+typedef KGenericFactory<XAMLExport, KoFilter> XAMLExportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonxamlexport, XAMLExportFactory( "kofficefilters" ) )
+
+
+XAMLExport::XAMLExport( KoFilter*, const char*, const QStringList& )
+ : KoFilter()
+{
+ m_gc.setAutoDelete( true );
+}
+
+KoFilter::ConversionStatus
+XAMLExport::convert( const QCString& from, const QCString& to )
+{
+ // TODO: ???
+ if ( to != "image/wvg+xml" || from != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+ if( !storeIn )
+ return KoFilter::StupidError;
+
+ QFile fileOut( m_chain->outputFile() );
+ if( !fileOut.open( IO_WriteOnly ) )
+ {
+ delete storeIn;
+ return KoFilter::StupidError;
+ }
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ m_stream = new QTextStream( &fileOut );
+ QString body;
+ m_body = new QTextStream( &body, IO_ReadWrite );
+ QString defs;
+ m_defs = new QTextStream( &defs, IO_ReadWrite );
+
+
+ // load the document and export it:
+ VDocument doc;
+ doc.load( docNode );
+ doc.accept( *this );
+
+ *m_stream << defs;
+ *m_stream << body;
+
+ fileOut.close();
+
+ delete m_stream;
+ delete m_defs;
+ delete m_body;
+
+ return KoFilter::OK;
+}
+
+void
+XAMLExport::visitVDocument( VDocument& document )
+{
+ // select all objects:
+ document.selection()->append();
+
+ // get the bounding box of the page
+ KoRect rect( 0, 0, document.width(), document.height() );
+
+ // standard header:
+ *m_defs <<
+ "<?xml version=\"1.0\" ?>\n" <<
+ /* "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" " <<* */
+ // "\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">"
+ /*<<*/ endl;
+
+ // Add one line comment to identify Content Creator,
+ // probably remove this later
+ // TODO: schemas
+ // http://schemas.microsoft.com/winfx/avalon/2005
+ // http://schemas.microsoft.com/2003/xaml
+ // need to mention defs too Defenitions namespace xmlns:def="Definition"
+ *m_defs <<
+ "<!-- Generator: Karbon14 WVG XAML Graphics export filter $VERSION/$DATE. -->" << endl;
+ *m_defs <<
+ "<Canvas xmlns=\"http://schemas.microsoft.com/winfx/avalon/2005\" Width=\"" << rect.width() <<
+ "Height=\"" << rect.height() << "\">" << endl;
+ *m_defs << "<Canvas.Resources>" << endl;
+
+ // bleuch: this is horrible, do something about it TODO
+ // Microsoft Acrylic has a transform group just like this
+ *m_body << "<Transform=\"scale(1, -1) Translate(0, -" << rect.height() << ")\">" << endl;
+
+ // we dont need the selection anymore:
+ document.selection()->clear();
+
+ // set up gc
+ XAMLGraphicsContext *gc = new XAMLGraphicsContext;
+ m_gc.push( gc );
+
+ // export layers:
+ VVisitor::visitVDocument( document );
+
+ // end tag:
+ *m_body << "</Canvas>" << endl;
+ *m_defs << "</Canvas.Resources>" << endl;
+ *m_body << "</Canvas>" << endl;
+}
+
+QString
+XAMLExport::getID( VObject *obj )
+{
+ if( obj && !obj->name().isEmpty() )
+ return QString( " Name=\"%1\"" ).arg( obj->name() );
+ return QString();
+}
+
+// which markup to use? Group or Canvas?
+// for now assume Group will work. TODO: Test properly!
+void
+XAMLExport::visitVGroup( VGroup& group )
+{
+ *m_body << "<Canvas" << getID( &group ) << ">" << endl;
+ VVisitor::visitVGroup( group );
+ *m_body << "</Canvas>" << endl;
+}
+
+void
+XAMLExport::visitVPath( VPath& composite )
+{
+ *m_body << "<Path" << getID( &composite );
+
+ VVisitor::visitVPath( composite );
+
+ getFill( *( composite.fill() ) );
+ getStroke( *( composite.stroke() ) );
+
+ QString d;
+ composite.saveSvgPath( d );
+ *m_body << " Data=\"" << d << "\" ";
+
+ if( composite.fillRule() != m_gc.current()->fillRule )
+ {
+ if( composite.fillRule() == evenOdd )
+ *m_body << " FillRule=\"EvenOdd\"";
+ else
+ *m_body << " FillRule=\"NonZero\"";
+ }
+
+ *m_body << " />" << endl;
+}
+
+void
+XAMLExport::visitVSubpath( VSubpath& )
+{
+}
+
+QString createUID()
+{
+ static unsigned int nr = 0;
+
+ return "defitem" + QString().setNum( nr++ );
+}
+
+void
+XAMLExport::getColorStops( const QPtrVector<VColorStop> &colorStops )
+{
+ for( unsigned int i = 0; i < colorStops.count() ; i++ )
+ {
+ *m_defs << "<GradientStop Color=\"";
+ getHexColor( m_defs, colorStops.at( i )->color );
+ *m_defs << "\" Offset=\"" << QString().setNum( colorStops.at( i )->rampPoint );
+ // XAML uses ARGB values and other methods such as masks for Transparency/Opacity # aa rrggbb
+ // *m_defs << "\" stop-opacity=\"" << colorStops.at( i )->color.opacity() << "\"" << " />" << endl;
+ // Maybe this only applies to gradients, need to check.
+ }
+}
+
+void
+XAMLExport::getGradient( const VGradient& grad )
+{
+ QString uid = createUID();
+ if( grad.type() == VGradient::linear )
+ {
+ // do linear grad
+ *m_defs << "<LinearGradientBrush id=\"" << uid << "\" ";
+ *m_defs << "GradientUnits=\"UserSpaceOnUse\" ";
+ *m_defs << "StartPoint=\"" << grad.origin().x() << ",";
+ *m_defs << grad.origin().y() << "\" ";
+ *m_defs << "EndPoint=\"" << grad.vector().x() << ",";
+ *m_defs << grad.vector().y() << "\" ";
+ if( grad.repeatMethod() == VGradient::reflect )
+ *m_defs << "SpreadMethod=\"Reflect\" ";
+ else if( grad.repeatMethod() == VGradient::repeat )
+ *m_defs << "SpreadMethod=\"Repeat\" ";
+ *m_defs << ">" << endl;
+
+ // color stops
+ getColorStops( grad.colorStops() );
+
+ *m_defs << "</LinearGradientBrush>" << endl;
+ *m_body << "url(#" << uid << ")";
+ }
+ else if( grad.type() == VGradient::radial )
+ {
+ // do radial grad
+ *m_defs << "<RadialGradientBrush Name=\"" << uid << "\" ";
+ // *m_defs << "gradientUnits=\"userSpaceOnUse\" "; // Absolute?
+ *m_defs << "Center=\"" << grad.origin().x() << ",";
+ *m_defs << grad.origin().y() << "\" ";
+ // Gradient Origin also known as Focus
+ *m_defs << "GradientOrigin=\"" << grad.focalPoint().x() << ",";
+ *m_defs << grad.focalPoint().y() << "\" ";
+ double r = sqrt( pow( grad.vector().x() - grad.origin().x(), 2 ) + pow( grad.vector().y() - grad.origin().y(), 2 ) );
+ *m_defs << "Radius=\"" << QString().setNum( r ) << "\" ";
+ if( grad.repeatMethod() == VGradient::reflect )
+ *m_defs << "SpreadMethod=\"Reflect\" ";
+ else if( grad.repeatMethod() == VGradient::repeat )
+ *m_defs << "SpreadMethod=\"Repeat\" ";
+ *m_defs << ">" << endl;
+
+ // color stops
+ getColorStops( grad.colorStops() );
+
+ *m_defs << "</RadialGradientBrush>" << endl;
+ *m_body << "url(#" << uid << ")";
+ }
+}
+
+void
+XAMLExport::getFill( const VFill& fill )
+{
+ *m_body << " Fill=\"";
+ if( fill.type() == VFill::none )
+ *m_body << "none";
+ else if( fill.type() == VFill::grad )
+ getGradient( fill.gradient() );
+ else
+ getHexColor( m_body, fill.color() );
+ *m_body << "\"";
+
+ if( fill.color().opacity() != m_gc.current()->fill.color().opacity() )
+ *m_body << " FillOpacity=\"" << fill.color().opacity() << "\"";
+}
+
+void
+XAMLExport::getStroke( const VStroke& stroke )
+{
+ if( stroke.type() != m_gc.current()->stroke.type() )
+ {
+ *m_body << " Stroke=\"";
+ if( stroke.type() == VStroke::none )
+ *m_body << "None";
+ else if( stroke.type() == VStroke::grad )
+ getGradient( stroke.gradient() );
+ else
+ getHexColor( m_body, stroke.color() );
+ *m_body << "\"";
+ }
+
+ if( stroke.color().opacity() != m_gc.current()->stroke.color().opacity() )
+ *m_body << " StrokeOpacity=\"" << stroke.color().opacity() << "\"";
+
+ if( stroke.lineWidth() != m_gc.current()->stroke.lineWidth() )
+ *m_body << " StrokeThickness=\"" << stroke.lineWidth() << "\"";
+
+ if( stroke.lineCap() != m_gc.current()->stroke.lineCap() )
+ {
+ if( stroke.lineCap() == VStroke::capButt )
+ *m_body << " StrokeLineCap=\"Butt\"";
+ else if( stroke.lineCap() == VStroke::capRound )
+ *m_body << " StrokeLineCap=\"round\"";
+ else if( stroke.lineCap() == VStroke::capSquare )
+ *m_body << " StrokeLineCap=\"square\"";
+ }
+
+ if( stroke.lineJoin() != m_gc.current()->stroke.lineJoin() )
+ {
+ if( stroke.lineJoin() == VStroke::joinMiter )
+ {
+ *m_body << " StrokeLineJoin=\"Miter\"";
+ *m_body << " StrokeMiterLimit=\"" << stroke.miterLimit() << "\"";
+ }
+ else if( stroke.lineJoin() == VStroke::joinRound )
+ *m_body << " StrokeLineJoin=\"Round\"";
+ else if( stroke.lineJoin() == VStroke::joinBevel )
+ *m_body << " StrokeLineJoin=\"Bevel\"";
+ }
+
+ // dash
+ if( stroke.dashPattern().array().count() > 0 )
+ {
+ *m_body << " StrokeDashOffset=\"" << stroke.dashPattern().offset() << "\"";
+ *m_body << " StrokeDashArray=\" ";
+
+ QValueListConstIterator<float> itr;
+ for(itr = stroke.dashPattern().array().begin(); itr != stroke.dashPattern().array().end(); ++itr )
+ {
+ *m_body << *itr << " ";
+ }
+ *m_body << "\"";
+ }
+}
+
+void
+XAMLExport::getHexColor( QTextStream *stream, const VColor& color )
+{
+ // Convert the various color-spaces to hex
+
+ QString Output;
+
+ VColor copy( color );
+ copy.setColorSpace( VColor::rgb );
+
+ Output.sprintf( "#%02x%02x%02x", int( copy[0] * 255.0 ), int( copy[1] * 255.0 ), int( copy[2] * 255.0 ) );
+
+ *stream << Output;
+}
+
+#include "xamlexport.moc"
+
diff --git a/filters/karbon/xaml/xamlexport.h b/filters/karbon/xaml/xamlexport.h
new file mode 100644
index 00000000..3d2701c6
--- /dev/null
+++ b/filters/karbon/xaml/xamlexport.h
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003 The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __XAMLEXPORT_H__
+#define __XAMLEXPORT_H__
+
+#include <KoFilter.h>
+
+#include "vvisitor.h"
+#include "vgradient.h"
+
+#include "xamlgraphiccontext.h"
+
+#include <qptrstack.h>
+
+class QTextStream;
+class VColor;
+class VPath;
+class VDocument;
+class VFill;
+class VGroup;
+class VLayer;
+class VSubpath;
+class VStroke;
+class VText;
+
+
+class XAMLExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ XAMLExport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~XAMLExport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+private:
+ virtual void visitVPath( VPath& composite );
+ virtual void visitVDocument( VDocument& document );
+ virtual void visitVGroup( VGroup& group );
+ virtual void visitVSubpath( VSubpath& path );
+ //virtual void visitVText( VText& text );
+
+ void getStroke( const VStroke& stroke );
+ void getColorStops( const QPtrVector<VColorStop> &colorStops );
+ void getFill( const VFill& fill );
+ void getGradient( const VGradient& grad );
+ void getHexColor( QTextStream *, const VColor& color );
+ QString getID( VObject *obj );
+
+ QTextStream* m_stream;
+ QTextStream* m_defs;
+ QTextStream* m_body;
+
+ QPtrStack<XAMLGraphicsContext> m_gc;
+};
+
+#endif
+
diff --git a/filters/karbon/xaml/xamlgraphiccontext.h b/filters/karbon/xaml/xamlgraphiccontext.h
new file mode 100644
index 00000000..db4a8363
--- /dev/null
+++ b/filters/karbon/xaml/xamlgraphiccontext.h
@@ -0,0 +1,46 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __XAMLGRAPHICSCONTEXT_H__
+#define __XAMLGRAPHICSCONTEXT_H__
+
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vfillrule.h>
+
+class XAMLGraphicsContext
+{
+public:
+ XAMLGraphicsContext()
+ {
+ stroke.setType( VStroke::none ); // default is no stroke
+ stroke.setLineWidth( 1.0 );
+ stroke.setLineCap( VStroke::capButt );
+ stroke.setLineJoin( VStroke::joinMiter );
+ fill.setColor( VColor( Qt::black ) );
+ fillRule = winding;
+ }
+ VFill fill;
+ VFillRule fillRule;
+ VStroke stroke;
+ QWMatrix matrix;
+ QFont font;
+};
+
+#endif
diff --git a/filters/karbon/xaml/xamlimport.cc b/filters/karbon/xaml/xamlimport.cc
new file mode 100644
index 00000000..297ff68d
--- /dev/null
+++ b/filters/karbon/xaml/xamlimport.cc
@@ -0,0 +1,1042 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, 2003, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "xamlimport.h"
+#include "color.h"
+#include <KoFilterChain.h>
+#include <kgenericfactory.h>
+#include <kdebug.h>
+#include <KoUnit.h>
+#include <KoGlobal.h>
+#include <shapes/vellipse.h>
+#include <shapes/vrectangle.h>
+#include <shapes/vpolygon.h>
+#include <commands/vtransformcmd.h>
+#include <core/vsegment.h>
+#include <core/vtext.h>
+#include <core/vglobal.h>
+#include <core/vgroup.h>
+#include <core/vimage.h>
+#include <core/vlayer.h>
+#include <qcolor.h>
+#include <qfile.h>
+#include <kfilterdev.h>
+
+typedef KGenericFactory<XAMLImport, KoFilter> XAMLImportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonxamlimport, XAMLImportFactory( "kofficefilters" ) )
+
+XAMLImport::XAMLImport(KoFilter *, const char *, const QStringList&) :
+ KoFilter(),
+ outdoc( "DOC" )
+{
+ m_gc.setAutoDelete( true );
+}
+
+XAMLImport::~XAMLImport()
+{
+}
+
+KoFilter::ConversionStatus XAMLImport::convert(const QCString& from, const QCString& to)
+{
+ // check for proper conversion
+ if( to != "application/x-karbon" || from != "image/wvg+xml" )
+ return KoFilter::NotImplemented;
+
+ //Find the last extension
+ QString strExt;
+ QString fileIn ( m_chain->inputFile() );
+ const int result=fileIn.findRev('.');
+ if (result>=0)
+ {
+ strExt=fileIn.mid(result).lower();
+ }
+
+ QString strMime; // Mime type of the compressor
+ if ((strExt==".gz") //in case of .svg.gz (logical extension)
+ ||(strExt==".wvgz")) //in case of .svgz (extension used prioritary)
+ strMime="application/x-gzip"; // Compressed with gzip
+ else if (strExt==".bz2") //in case of .svg.bz2 (logical extension)
+ strMime="application/x-bzip2"; // Compressed with bzip2
+ else
+ strMime="text/plain";
+
+ kdDebug(30514) << "File extension: -" << strExt << "- Compression: " << strMime << endl;
+
+ QIODevice* in = KFilterDev::deviceForFile(fileIn,strMime);
+
+ if (!in->open(IO_ReadOnly))
+ {
+ kdError(30514) << "Cannot open file! Aborting!" << endl;
+ delete in;
+ return KoFilter::FileNotFound;
+ }
+
+ int line, col;
+ QString errormessage;
+ const bool parsed=inpdoc.setContent( in, &errormessage, &line, &col );
+ in->close();
+ delete in;
+ if ( ! parsed )
+ {
+ kdError(30514) << "Error while parsing file: "
+ << "at line " << line << " column: " << col
+ << " message: " << errormessage << endl;
+ // ### TODO: feedback to the user
+ return KoFilter::ParsingError;
+ }
+
+ // Do the conversion!
+ convert();
+
+ KoStoreDevice* out = m_chain->storageFile( "root", KoStore::Write );
+ if( !out )
+ {
+ kdError(30514) << "Unable to open output file!" << endl;
+ return KoFilter::StorageCreationError;
+ }
+ QCString cstring = outdoc.toCString(); // utf-8 already
+ out->writeBlock( cstring.data(), cstring.length() );
+
+ return KoFilter::OK; // was successful
+}
+
+void
+XAMLImport::convert()
+{
+ XAMLGraphicsContext *gc = new XAMLGraphicsContext;
+ QDomElement docElem = inpdoc.documentElement();
+ KoRect bbox( 0, 0, 550.0, 841.0 );
+ double width = !docElem.attribute( "width" ).isEmpty() ? parseUnit( docElem.attribute( "width" ), true, false, bbox ) : 550.0;
+ double height = !docElem.attribute( "height" ).isEmpty() ? parseUnit( docElem.attribute( "height" ), false, true, bbox ) : 841.0;
+ m_document.setWidth( width );
+ m_document.setHeight( height );
+ m_outerRect = m_document.boundingBox();
+
+ // undo y-mirroring
+ if( !docElem.attribute( "viewBox" ).isEmpty() )
+ {
+ // allow for viewbox def with ',' or whitespace
+ QString viewbox( docElem.attribute( "viewBox" ) );
+ QStringList points = QStringList::split( ' ', viewbox.replace( ',', ' ').simplifyWhiteSpace() );
+
+ gc->matrix.scale( width / points[2].toFloat() , height / points[3].toFloat() );
+ m_outerRect.setWidth( m_outerRect.width() * ( points[2].toFloat() / width ) );
+ m_outerRect.setHeight( m_outerRect.height() * ( points[3].toFloat() / height ) );
+ }
+ m_gc.push( gc );
+ parseGroup( 0L, docElem );
+
+ QWMatrix mat;
+ mat.scale( 1, -1 );
+ mat.translate( 0, -m_document.height() );
+ VTransformCmd trafo( 0L, mat );
+ trafo.visit( m_document );
+ outdoc = m_document.saveXML();
+}
+
+#define DPI 90
+
+double
+XAMLImport::toPercentage( QString s )
+{
+ if( s.endsWith( "%" ) )
+ return s.remove( '%' ).toDouble();
+ else
+ return s.toDouble() * 100.0;
+}
+
+double
+XAMLImport::fromPercentage( QString s )
+{
+ if( s.endsWith( "%" ) )
+ return s.remove( '%' ).toDouble() / 100.0;
+ else
+ return s.toDouble();
+}
+
+// parses the number into parameter number
+const char *
+getNumber( const char *ptr, double &number )
+{
+ int integer, exponent;
+ double decimal, frac;
+ int sign, expsign;
+
+ exponent = 0;
+ integer = 0;
+ frac = 1.0;
+ decimal = 0;
+ sign = 1;
+ expsign = 1;
+
+ // read the sign
+ if(*ptr == '+')
+ ptr++;
+ else if(*ptr == '-')
+ {
+ ptr++;
+ sign = -1;
+ }
+
+ // read the integer part
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ integer = (integer * 10) + *(ptr++) - '0';
+ if(*ptr == '.') // read the decimals
+ {
+ ptr++;
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ decimal += (*(ptr++) - '0') * (frac *= 0.1);
+ }
+
+ if(*ptr == 'e' || *ptr == 'E') // read the exponent part
+ {
+ ptr++;
+
+ // read the sign of the exponent
+ if(*ptr == '+')
+ ptr++;
+ else if(*ptr == '-')
+ {
+ ptr++;
+ expsign = -1;
+ }
+
+ exponent = 0;
+ while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
+ {
+ exponent *= 10;
+ exponent += *ptr - '0';
+ ptr++;
+ }
+ }
+ number = integer + decimal;
+ number *= sign * pow( (double)10, double( expsign * exponent ) );
+
+ return ptr;
+}
+
+
+double
+XAMLImport::parseUnit( const QString &unit, bool horiz, bool vert, KoRect bbox )
+{
+ // TODO : percentage?
+ double value = 0;
+ const char *start = unit.latin1();
+ if(!start) {
+ return 0;
+ }
+ const char *end = getNumber( start, value );
+
+ if( uint( end - start ) < unit.length() )
+ {
+ if( unit.right( 2 ) == "pt" )
+ value = ( value / 72.0 ) * DPI;
+ else if( unit.right( 2 ) == "cm" )
+ value = ( value / 2.54 ) * DPI;
+ else if( unit.right( 2 ) == "pc" )
+ value = ( value / 6.0 ) * DPI;
+ else if( unit.right( 2 ) == "mm" )
+ value = ( value / 25.4 ) * DPI;
+ else if( unit.right( 2 ) == "in" )
+ value = value * DPI;
+ else if( unit.right( 2 ) == "pt" )
+ value = ( value / 72.0 ) * DPI;
+ else if( unit.right( 2 ) == "em" )
+ value = value * m_gc.current()->font.pointSize() / ( sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 ) );
+ else if( unit.right( 1 ) == "%" )
+ {
+ if( horiz && vert )
+ value = ( value / 100.0 ) * (sqrt( pow( bbox.width(), 2 ) + pow( bbox.height(), 2 ) ) / sqrt( 2.0 ) );
+ else if( horiz )
+ value = ( value / 100.0 ) * bbox.width();
+ else if( vert )
+ value = ( value / 100.0 ) * bbox.height();
+ }
+ }
+ /*else
+ {
+ if( m_gc.current() )
+ {
+ if( horiz && vert )
+ value *= sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 );
+ else if( horiz )
+ value /= m_gc.current()->matrix.m11();
+ else if( vert )
+ value /= m_gc.current()->matrix.m22();
+ }
+ }*/
+ return value;
+}
+
+QColor
+XAMLImport::parseColor( const QString &rgbColor )
+{
+ int r, g, b;
+ keywordToRGB( rgbColor, r, g, b );
+ return QColor( r, g, b );
+}
+
+void
+XAMLImport::parseColor( VColor &color, const QString &s )
+{
+ if( s.startsWith( "rgb(" ) )
+ {
+ QString parse = s.stripWhiteSpace();
+ QStringList colors = QStringList::split( ',', parse );
+ QString r = colors[0].right( ( colors[0].length() - 4 ) );
+ QString g = colors[1];
+ QString b = colors[2].left( ( colors[2].length() - 1 ) );
+
+ if( r.contains( "%" ) )
+ {
+ r = r.left( r.length() - 1 );
+ r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( g.contains( "%" ) )
+ {
+ g = g.left( g.length() - 1 );
+ g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) );
+ }
+
+ if( b.contains( "%" ) )
+ {
+ b = b.left( b.length() - 1 );
+ b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) );
+ }
+
+ QColor c( r.toInt(), g.toInt(), b.toInt() );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+ else
+ {
+ QString rgbColor = s.stripWhiteSpace();
+ QColor c;
+ if( rgbColor.startsWith( "#" ) )
+ c.setNamedColor( rgbColor );
+ else
+ c = parseColor( rgbColor );
+ color.set( c.red() / 255.0, c.green() / 255.0, c.blue() / 255.0 );
+ }
+}
+
+void
+XAMLImport::parseColorStops( VGradient *gradient, const QDomElement &e )
+{
+ VColor c;
+ for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement stop = n.toElement();
+ if( stop.tagName() == "stop" )
+ {
+ float offset;
+ QString temp = stop.attribute( "offset" );
+ if( temp.contains( '%' ) )
+ {
+ temp = temp.left( temp.length() - 1 );
+ offset = temp.toFloat() / 100.0;
+ }
+ else
+ offset = temp.toFloat();
+
+ if( !stop.attribute( "stop-color" ).isEmpty() )
+ parseColor( c, stop.attribute( "stop-color" ) );
+ else
+ {
+ // try style attr
+ QString style = stop.attribute( "style" ).simplifyWhiteSpace();
+ QStringList substyles = QStringList::split( ';', style );
+ for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ QStringList substyle = QStringList::split( ':', (*it) );
+ QString command = substyle[0].stripWhiteSpace();
+ QString params = substyle[1].stripWhiteSpace();
+ if( command == "stop-color" )
+ parseColor( c, params );
+ if( command == "stop-opacity" )
+ c.setOpacity( params.toDouble() );
+ }
+
+ }
+ if( !stop.attribute( "stop-opacity" ).isEmpty() )
+ c.setOpacity( stop.attribute( "stop-opacity" ).toDouble() );
+ gradient->addStop( c, offset, 0.5 );
+ }
+ }
+}
+
+void
+XAMLImport::parseGradient( const QDomElement &e )
+{
+ GradientHelper gradhelper;
+ gradhelper.gradient.clearStops();
+ gradhelper.gradient.setRepeatMethod( VGradient::none );
+
+ QString href = e.attribute( "xlink:href" ).mid( 1 );
+ if( !href.isEmpty() )
+ {
+ //kdDebug() << "Indexing with href : " << href.latin1() << endl;
+ gradhelper.gradient = m_gradients[ href ].gradient;
+ }
+
+ gradhelper.bbox = e.attribute( "gradientUnits" ) != "userSpaceOnUse";
+
+ if( e.tagName() == "linearGradient" )
+ {
+ if( gradhelper.bbox )
+ {
+ gradhelper.gradient.setOrigin( KoPoint( toPercentage( e.attribute( "x1", "0%" ) ), toPercentage( e.attribute( "y1", "0%" ) ) ) );
+ gradhelper.gradient.setVector( KoPoint( toPercentage( e.attribute( "x2", "100%" ) ), toPercentage( e.attribute( "y2", "0%" ) ) ) );
+ }
+ else
+ {
+ gradhelper.gradient.setOrigin( KoPoint( e.attribute( "x1" ).toDouble(), e.attribute( "y1" ).toDouble() ) );
+ gradhelper.gradient.setVector( KoPoint( e.attribute( "x2" ).toDouble(), e.attribute( "y2" ).toDouble() ) );
+ }
+ }
+ else
+ {
+ if( gradhelper.bbox )
+ {
+ gradhelper.gradient.setOrigin( KoPoint( toPercentage( e.attribute( "cx", "50%" ) ), toPercentage( e.attribute( "cy", "50%" ) ) ) );
+ gradhelper.gradient.setVector( KoPoint( toPercentage( e.attribute( "cx", "50%" ) ) + toPercentage( e.attribute( "r", "50%" ) ),
+ toPercentage( e.attribute( "cy", "50%" ) ) ) );
+ gradhelper.gradient.setFocalPoint( KoPoint( toPercentage( e.attribute( "fx", "50%" ) ), toPercentage( e.attribute( "fy", "50%" ) ) ) );
+ }
+ else
+ {
+ gradhelper.gradient.setOrigin( KoPoint( e.attribute( "cx" ).toDouble(), e.attribute( "cy" ).toDouble() ) );
+ gradhelper.gradient.setFocalPoint( KoPoint( e.attribute( "fx" ).toDouble(), e.attribute( "fy" ).toDouble() ) );
+ gradhelper.gradient.setVector( KoPoint( e.attribute( "cx" ).toDouble() + e.attribute( "r" ).toDouble(), e.attribute( "cy" ).toDouble() ) );
+ }
+ gradhelper.gradient.setType( VGradient::radial );
+ }
+ // handle spread method
+ QString spreadMethod = e.attribute( "spreadMethod" );
+ if( !spreadMethod.isEmpty() )
+ {
+ if( spreadMethod == "reflect" )
+ gradhelper.gradient.setRepeatMethod( VGradient::reflect );
+ else if( spreadMethod == "repeat" )
+ gradhelper.gradient.setRepeatMethod( VGradient::repeat );
+ }
+ parseColorStops( &gradhelper.gradient, e );
+ //gradient.setGradientTransform( parseTransform( e.attribute( "gradientTransform" ) ) );
+ gradhelper.gradientTransform = VPath::parseTransform( e.attribute( "gradientTransform" ) );
+ m_gradients.insert( e.attribute( "id" ), gradhelper );
+}
+
+void
+XAMLImport::parsePA( VObject *obj, XAMLGraphicsContext *gc, const QString &command, const QString &params )
+{
+ VColor fillcolor = gc->fill.color();
+ VColor strokecolor = gc->stroke.color();
+
+ if( command == "fill" )
+ {
+ if( params == "none" )
+ gc->fill.setType( VFill::none );
+ else if( params.startsWith( "url(" ) )
+ {
+ unsigned int start = params.find("#") + 1;
+ unsigned int end = params.findRev(")");
+ QString key = params.mid( start, end - start );
+ gc->fill.gradient() = m_gradients[ key ].gradient;
+ if( m_gradients[ key ].bbox )
+ {
+ // adjust to bbox
+ KoRect bbox = obj->boundingBox();
+ //kdDebug() << "bbox x : " << bbox.x() << endl;
+ //kdDebug() << "!!!!!!bbox y : " << bbox.y() << endl;
+ //kdDebug() << gc->fill.gradient().origin().x() << endl;
+ //kdDebug() << gc->fill.gradient().vector().x() << endl;
+ double offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().origin().x() ), true, false, bbox );
+ double offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().origin().y() ), false, true, bbox );
+ gc->fill.gradient().setOrigin( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().focalPoint().x() ), true, false, bbox );
+ offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().focalPoint().y() ), false, true, bbox );
+ gc->fill.gradient().setFocalPoint( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ offsetx = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().vector().x() ), true, false, bbox );
+ offsety = parseUnit( QString( "%1%" ).arg( gc->fill.gradient().vector().y() ), false, true, bbox );
+ gc->fill.gradient().setVector( KoPoint( bbox.x() + offsetx, bbox.y() + offsety ) );
+ //kdDebug() << offsety << endl;
+ //kdDebug() << gc->fill.gradient().origin().x() << endl;
+ //kdDebug() << gc->fill.gradient().origin().y() << endl;
+ //kdDebug() << gc->fill.gradient().vector().x() << endl;
+ //kdDebug() << gc->fill.gradient().vector().y() << endl;
+ }
+ gc->fill.gradient().transform( m_gradients[ key ].gradientTransform );
+ if( !m_gradients[ key ].bbox )
+ gc->fill.gradient().transform( gc->matrix );
+ gc->fill.setType( VFill::grad );
+ }
+ else
+ {
+ parseColor( fillcolor, params );
+ gc->fill.setType( VFill::solid );
+ }
+ }
+ else if( command == "fill-rule" )
+ {
+ if( params == "nonzero" )
+ gc->fillRule = winding;
+ else if( params == "evenodd" )
+ gc->fillRule = evenOdd;
+ }
+ else if( command == "stroke" )
+ {
+ if( params == "none" )
+ gc->stroke.setType( VStroke::none );
+ else if( params.startsWith( "url(" ) )
+ {
+ unsigned int start = params.find("#") + 1;
+ unsigned int end = params.findRev(")");
+ QString key = params.mid( start, end - start );
+ gc->stroke.gradient() = m_gradients[ key ].gradient;
+ gc->stroke.gradient().transform( m_gradients[ key ].gradientTransform );
+ gc->stroke.gradient().transform( gc->matrix );
+ gc->stroke.setType( VStroke::grad );
+ }
+ else
+ {
+ parseColor( strokecolor, params );
+ gc->stroke.setType( VStroke::solid );
+ }
+ }
+ else if( command == "stroke-width" )
+ gc->stroke.setLineWidth( parseUnit( params, true, true, m_outerRect ) );
+ else if( command == "stroke-linejoin" )
+ {
+ if( params == "miter" )
+ gc->stroke.setLineJoin( VStroke::joinMiter );
+ else if( params == "round" )
+ gc->stroke.setLineJoin( VStroke::joinRound );
+ else if( params == "bevel" )
+ gc->stroke.setLineJoin( VStroke::joinBevel );
+ }
+ else if( command == "stroke-linecap" )
+ {
+ if( params == "butt" )
+ gc->stroke.setLineCap( VStroke::capButt );
+ else if( params == "round" )
+ gc->stroke.setLineCap( VStroke::capRound );
+ else if( params == "square" )
+ gc->stroke.setLineCap( VStroke::capSquare );
+ }
+ else if( command == "stroke-miterlimit" )
+ gc->stroke.setMiterLimit( params.toFloat() );
+ else if( command == "stroke-dasharray" )
+ {
+ QValueList<float> array;
+ if(params != "none")
+ {
+ QStringList dashes = QStringList::split( ' ', params );
+ for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
+ array.append( (*it).toFloat() );
+ }
+ gc->stroke.dashPattern().setArray( array );
+ }
+ else if( command == "stroke-dashoffset" )
+ gc->stroke.dashPattern().setOffset( params.toFloat() );
+ // handle opacity
+ else if( command == "stroke-opacity" )
+ strokecolor.setOpacity( fromPercentage( params ) );
+ else if( command == "fill-opacity" )
+ fillcolor.setOpacity( fromPercentage( params ) );
+ else if( command == "opacity" )
+ {
+ fillcolor.setOpacity( fromPercentage( params ) );
+ strokecolor.setOpacity( fromPercentage( params ) );
+ }
+ else if( command == "font-family" )
+ {
+ QString family = params;
+ family.replace( '\'' , ' ' );
+ gc->font.setFamily( family );
+ }
+ else if( command == "font-size" )
+ {
+ float pointSize = parseUnit( params );
+ pointSize *= gc->matrix.m22() > 0 ? gc->matrix.m22() : -1.0 * gc->matrix.m22();
+ gc->font.setPointSizeFloat( pointSize );
+ }
+ else if( command == "text-decoration" )
+ {
+ if( params == "line-through" )
+ gc->font.setStrikeOut( true );
+ else if( params == "underline" )
+ gc->font.setUnderline( true );
+ }
+ if( gc->fill.type() != VFill::none )
+ gc->fill.setColor( fillcolor, false );
+ //if( gc->stroke.type() == VStroke::solid )
+ gc->stroke.setColor( strokecolor );
+}
+
+void
+XAMLImport::addGraphicContext()
+{
+ XAMLGraphicsContext *gc = new XAMLGraphicsContext;
+ // set as default
+ if( m_gc.current() )
+ *gc = *( m_gc.current() );
+ m_gc.push( gc );
+}
+
+void
+XAMLImport::setupTransform( const QDomElement &e )
+{
+ XAMLGraphicsContext *gc = m_gc.current();
+
+ QWMatrix mat = VPath::parseTransform( e.attribute( "transform" ) );
+ gc->matrix = mat * gc->matrix;
+}
+
+void
+XAMLImport::parseStyle( VObject *obj, const QDomElement &e )
+{
+ XAMLGraphicsContext *gc = m_gc.current();
+ if( !gc ) return;
+
+ // try normal PA
+ if( !e.attribute( "fill" ).isEmpty() )
+ parsePA( obj, gc, "fill", e.attribute( "fill" ) );
+ if( !e.attribute( "fill-rule" ).isEmpty() )
+ parsePA( obj, gc, "fill-rule", e.attribute( "fill-rule" ) );
+ if( !e.attribute( "stroke" ).isEmpty() )
+ parsePA( obj, gc, "stroke", e.attribute( "stroke" ) );
+ if( !e.attribute( "stroke-width" ).isEmpty() )
+ parsePA( obj, gc, "stroke-width", e.attribute( "stroke-width" ) );
+ if( !e.attribute( "stroke-linejoin" ).isEmpty() )
+ parsePA( obj, gc, "stroke-linejoin", e.attribute( "stroke-linejoin" ) );
+ if( !e.attribute( "stroke-linecap" ).isEmpty() )
+ parsePA( obj, gc, "stroke-linecap", e.attribute( "stroke-linecap" ) );
+ if( !e.attribute( "stroke-dasharray" ).isEmpty() )
+ parsePA( obj, gc, "stroke-dasharray", e.attribute( "stroke-dasharray" ) );
+ if( !e.attribute( "stroke-dashoffset" ).isEmpty() )
+ parsePA( obj, gc, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) );
+ if( !e.attribute( "stroke-opacity" ).isEmpty() )
+ parsePA( obj, gc, "stroke-opacity", e.attribute( "stroke-opacity" ) );
+ if( !e.attribute( "stroke-miterlimit" ).isEmpty() )
+ parsePA( obj, gc, "stroke-miterlimit", e.attribute( "stroke-miterlimit" ) );
+ if( !e.attribute( "fill-opacity" ).isEmpty() )
+ parsePA( obj, gc, "fill-opacity", e.attribute( "fill-opacity" ) );
+ if( !e.attribute( "opacity" ).isEmpty() )
+ parsePA( obj, gc, "opacity", e.attribute( "opacity" ) );
+
+ // try style attr
+ QString style = e.attribute( "style" ).simplifyWhiteSpace();
+ QStringList substyles = QStringList::split( ';', style );
+ for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
+ {
+ QStringList substyle = QStringList::split( ':', (*it) );
+ QString command = substyle[0].stripWhiteSpace();
+ QString params = substyle[1].stripWhiteSpace();
+ parsePA( obj, gc, command, params );
+ }
+
+ obj->setFill( gc->fill );
+ if( dynamic_cast<VPath *>( obj ) )
+ dynamic_cast<VPath *>( obj )->setFillRule( gc->fillRule );
+ // stroke scaling
+ double lineWidth = gc->stroke.lineWidth();
+ gc->stroke.setLineWidth( lineWidth * sqrt( pow( m_gc.current()->matrix.m11(), 2 ) + pow( m_gc.current()->matrix.m22(), 2 ) ) / sqrt( 2.0 ) );
+ obj->setStroke( gc->stroke );
+ gc->stroke.setLineWidth( lineWidth );
+}
+
+void
+XAMLImport::parseFont( const QDomElement &e )
+{
+ XAMLGraphicsContext *gc = m_gc.current();
+ if( !gc ) return;
+
+ if( ! e.attribute( "font-family" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "font-family", e.attribute( "font-family" ) );
+ if( ! e.attribute( "font-size" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "font-size", e.attribute( "font-size" ) );
+ if( ! e.attribute( "text-decoration" ).isEmpty() )
+ parsePA( 0L, m_gc.current(), "text-decoration", e.attribute( "text-decoration" ) );
+}
+
+void
+XAMLImport::parseGroup( VGroup *grp, const QDomElement &e )
+{
+ bool isDef = false;
+ if( e.tagName() == "defs" )
+ isDef = true;
+
+ for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement b = n.toElement();
+ if( b.isNull() ) continue;
+ VObject *obj = 0L;
+ if( b.tagName() == "g" )
+ {
+ VGroup *group;
+ if ( grp )
+ group = new VGroup( grp );
+ else
+ group = new VGroup( &m_document );
+
+ addGraphicContext();
+ setupTransform( b );
+ parseStyle( group, b );
+ parseFont( b );
+ parseGroup( group, b );
+
+ // handle id
+ if( !b.attribute("id").isEmpty() )
+ group->setName( b.attribute("id") );
+ if( grp )
+ grp->append( group );
+ else
+ m_document.append( group );
+ delete( m_gc.pop() );
+ continue;
+ }
+ if( b.tagName() == "defs" )
+ {
+ parseGroup( 0L, b ); // try for gradients at least
+ continue;
+ }
+ else if( b.tagName() == "linearGradient" || b.tagName() == "radialGradient" )
+ {
+ parseGradient( b );
+ continue;
+ }
+ else if( b.tagName() == "rect" ||
+ b.tagName() == "ellipse" ||
+ b.tagName() == "circle" ||
+ b.tagName() == "line" ||
+ b.tagName() == "polyline" ||
+ b.tagName() == "polygon" ||
+ b.tagName() == "path" ||
+ b.tagName() == "image" )
+ {
+ if (!isDef)
+ obj = createObject( b );
+ else
+ m_paths.insert( b.attribute( "id" ), b );
+ }
+ else if( b.tagName() == "text" )
+ {
+ if( isDef )
+ m_paths.insert( b.attribute( "id" ), b );
+ else
+ createText( grp, b );
+ }
+ else if( b.tagName() == "use" )
+ {
+ double tx = b.attribute( "x" ).toDouble();
+ double ty = b.attribute( "y" ).toDouble();
+
+ if( !b.attribute( "xlink:href" ).isEmpty() )
+ {
+ QString params = b.attribute( "xlink:href" );
+ unsigned int start = params.find("#") + 1;
+ unsigned int end = params.findRev(")");
+ QString key = params.mid( start, end - start );
+ if(m_paths.contains(key))
+ {
+ QDomElement a = m_paths[key];
+ obj = createObject( a );
+ m_gc.current()->matrix.translate(tx,ty);
+ parsePA( grp, m_gc.current(), "fill", b.attribute( "fill" ) );
+ }
+ }
+ }
+ if( !obj ) continue;
+ VTransformCmd trafo( 0L, m_gc.current()->matrix );
+ trafo.visit( *obj );
+ parseStyle( obj, b );
+ // handle id
+ if( !b.attribute("id").isEmpty() )
+ obj->setName( b.attribute("id") );
+ if( grp )
+ grp->append( obj );
+ else
+ m_document.append( obj );
+ delete( m_gc.pop() );
+ }
+}
+
+VObject* XAMLImport::findObject( const QString &name, VGroup* group )
+{
+ if( ! group )
+ return 0L;
+
+ VObjectListIterator itr = group->objects();
+
+ for( uint objcount = 1; itr.current(); ++itr, objcount++ )
+ if( itr.current()->state() != VObject::deleted )
+ {
+ if( itr.current()->name() == name )
+ return itr.current();
+
+ if( dynamic_cast<VGroup *>( itr.current() ) )
+ {
+ VObject *obj = findObject( name, dynamic_cast<VGroup *>( itr.current() ) );
+ if( obj )
+ return obj;
+ }
+ }
+
+ return 0L;
+}
+
+VObject* XAMLImport::findObject( const QString &name )
+{
+ QPtrVector<VLayer> vector;
+ m_document.layers().toVector( &vector );
+ for( int i = vector.count() - 1; i >= 0; i-- )
+ {
+ if ( vector[i]->state() != VObject::deleted )
+ {
+ VObject* obj = findObject( name, dynamic_cast<VGroup *>( vector[i] ) );
+ if( obj )
+ return obj;
+ }
+ }
+
+ return 0L;
+}
+
+void XAMLImport::createText( VGroup *grp, const QDomElement &b )
+{
+ VText *text = 0L;
+ QString content;
+ VSubpath base( 0L );
+ VPath *path = 0L;
+
+ addGraphicContext();
+ setupTransform( b );
+ VTransformCmd trafo( 0L, m_gc.current()->matrix );
+
+ parseFont( b );
+
+ if( b.hasChildNodes() )
+ {
+ if( base.isEmpty() && ! b.attribute( "x" ).isEmpty() && ! b.attribute( "y" ).isEmpty() )
+ {
+ double x = parseUnit( b.attribute( "x" ) );
+ double y = parseUnit( b.attribute( "y" ) );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + 10, y ) );
+ }
+
+ for( QDomNode n = b.firstChild(); !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement();
+ if( e.isNull() )
+ {
+ content += n.toCharacterData().data();
+ }
+ else if( e.tagName() == "textPath" )
+ {
+ if( e.attribute( "xlink:href" ).isEmpty() )
+ continue;
+
+ QString uri = e.attribute( "xlink:href" );
+ unsigned int start = uri.find("#") + 1;
+ unsigned int end = uri.findRev(")");
+ QString key = uri.mid( start, end - start );
+ if( ! m_paths.contains(key) )
+ {
+ VObject* obj = findObject( key );
+ if( obj )
+ path = dynamic_cast<VPath*>( obj );
+ }
+ else
+ {
+ QDomElement p = m_paths[key];
+ path = dynamic_cast<VPath*>( createObject( p ) );
+ if( path )
+ path->setState( VObject::deleted );
+ }
+ if( ! path )
+ continue;
+ base = *path->paths().getFirst();
+ content += e.text();
+ }
+ else if( e.tagName() == "tspan" )
+ {
+ // only use text of tspan element, as we are not supporting text
+ // with different styles
+ content += e.text();
+ if( base.isEmpty() && ! e.attribute( "x" ).isEmpty() && ! e.attribute( "y" ).isEmpty() )
+ {
+ QStringList posX = QStringList::split( ", ", e.attribute( "x" ) );
+ QStringList posY = QStringList::split( ", ", e.attribute( "y" ) );
+ if( posX.count() && posY.count() )
+ {
+ double x = parseUnit( posX.first() );
+ double y = parseUnit( posY.first() );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + 10, y ) );
+ }
+ }
+ }
+ else if( e.tagName() == "tref" )
+ {
+ if( e.attribute( "xlink:href" ).isEmpty() )
+ continue;
+
+ QString uri = e.attribute( "xlink:href" );
+ unsigned int start = uri.find("#") + 1;
+ unsigned int end = uri.findRev(")");
+ QString key = uri.mid( start, end - start );
+
+ if( ! m_paths.contains(key) )
+ {
+ VObject* obj = findObject( key );
+ if( obj )
+ content += dynamic_cast<VText*>( obj )->text();
+ }
+ else
+ {
+ QDomElement p = m_paths[key];
+ content += p.text();
+ }
+ }
+ else
+ continue;
+ }
+ text = new VText( m_gc.current()->font, base, VText::Above, VText::Left, content.simplifyWhiteSpace() );
+ }
+ else
+ {
+ VSubpath base( 0L );
+ double x = parseUnit( b.attribute( "x" ) );
+ double y = parseUnit( b.attribute( "y" ) );
+ base.moveTo( KoPoint( x, y ) );
+ base.lineTo( KoPoint( x + 10, y ) );
+ text = new VText( m_gc.current()->font, base, VText::Above, VText::Left, b.text().simplifyWhiteSpace() );
+ }
+
+ if( text )
+ {
+ text->setParent( &m_document );
+
+ parseStyle( text, b );
+ trafo.visit( *text );
+
+ if( !b.attribute("id").isEmpty() )
+ text->setName( b.attribute("id") );
+
+ if( grp )
+ grp->append( text );
+ else
+ m_document.append( text );
+ }
+ delete( m_gc.pop() );
+}
+
+VObject* XAMLImport::createObject( const QDomElement &b )
+{
+ if( b.tagName() == "rect" )
+ {
+ addGraphicContext();
+ double x = parseUnit( b.attribute( "x" ), true, false, m_outerRect );
+ double y = parseUnit( b.attribute( "y" ), false, true, m_outerRect );
+ double width = parseUnit( b.attribute( "width" ), true, false, m_outerRect );
+ double height = parseUnit( b.attribute( "height" ), false, true, m_outerRect );
+ setupTransform( b );
+ return new VRectangle( 0L, KoPoint( x, height + y ) , width, height );
+ }
+ else if( b.tagName() == "ellipse" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ double rx = parseUnit( b.attribute( "rx" ) );
+ double ry = parseUnit( b.attribute( "ry" ) );
+ double left = parseUnit( b.attribute( "cx" ) ) - rx;
+ double top = parseUnit( b.attribute( "cy" ) ) - ry;
+ return new VEllipse( 0L, KoPoint( left, top ), rx * 2.0, ry * 2.0 );
+ }
+ else if( b.tagName() == "circle" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ double r = parseUnit( b.attribute( "r" ) );
+ double left = parseUnit( b.attribute( "cx" ) ) - r;
+ double top = parseUnit( b.attribute( "cy" ) ) - r;
+ return new VEllipse( 0L, KoPoint( left, top ), r * 2.0, r * 2.0 );
+ }
+ else if( b.tagName() == "line" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ VPath *path = new VPath( &m_document );
+ double x1 = b.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x1" ) );
+ double y1 = b.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y1" ) );
+ double x2 = b.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x2" ) );
+ double y2 = b.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y2" ) );
+ path->moveTo( KoPoint( x1, y1 ) );
+ path->lineTo( KoPoint( x2, y2 ) );
+ return path;
+ }
+ else if( b.tagName() == "polyline" || b.tagName() == "polygon" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ VPath *path = new VPath( &m_document );
+ bool bFirst = true;
+
+ QString points = b.attribute( "points" ).simplifyWhiteSpace();
+ points.replace( ',', ' ' );
+ points.remove( '\r' );
+ points.remove( '\n' );
+ QStringList pointList = QStringList::split( ' ', points );
+ for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); ++it)
+ {
+ KoPoint point;
+ point.setX( (*it).toDouble() );
+ point.setY( (*it).toDouble() );
+ if( bFirst )
+ {
+ path->moveTo( point );
+ bFirst = false;
+ }
+ else
+ path->lineTo( point );
+ }
+ if( b.tagName() == "polygon" ) path->close();
+ return path;
+ }
+ else if( b.tagName() == "path" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ VPath *path = new VPath( &m_document );
+ path->loadSvgPath( b.attribute( "d" ) );
+ return path;
+ }
+ else if( b.tagName() == "image" )
+ {
+ addGraphicContext();
+ setupTransform( b );
+ QString fname = b.attribute("xlink:href");
+ return new VImage( 0L, fname );
+ }
+
+ return 0L;
+}
+
+#include <xamlimport.moc>
diff --git a/filters/karbon/xaml/xamlimport.h b/filters/karbon/xaml/xamlimport.h
new file mode 100644
index 00000000..05763419
--- /dev/null
+++ b/filters/karbon/xaml/xamlimport.h
@@ -0,0 +1,91 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __XAMLIMPORT_H__
+#define __XAMLIMPORT_H__
+
+#include <KoFilter.h>
+#include <qdom.h>
+#include <qmap.h>
+#include <qptrstack.h>
+#include <core/vdocument.h>
+#include <core/vgradient.h>
+#include <core/vfill.h>
+#include <core/vstroke.h>
+#include <core/vfillrule.h>
+#include "xamlgraphiccontext.h"
+
+class VGroup;
+class VPath;
+
+class XAMLImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ XAMLImport(KoFilter *parent, const char *name, const QStringList&);
+ virtual ~XAMLImport();
+
+ virtual KoFilter::ConversionStatus convert(const QCString& from, const QCString& to);
+
+protected:
+ class GradientHelper
+ {
+ public:
+ GradientHelper()
+ {
+ bbox = true;
+ }
+ VGradient gradient;
+ bool bbox;
+ QWMatrix gradientTransform;
+ };
+
+ void parseGroup( VGroup *, const QDomElement & );
+ void parseStyle( VObject *, const QDomElement & );
+ void parsePA( VObject *, XAMLGraphicsContext *, const QString &, const QString & );
+ void parseGradient( const QDomElement & );
+ void parseColorStops( VGradient *, const QDomElement & );
+ double parseUnit( const QString &, bool horiz = false, bool vert = false, KoRect bbox = KoRect() );
+ void parseColor( VColor &, const QString & );
+ QColor parseColor( const QString & );
+ double toPercentage( QString );
+ double fromPercentage( QString );
+ void setupTransform( const QDomElement & );
+ void addGraphicContext();
+ QDomDocument inpdoc;
+ QDomDocument outdoc;
+ void convert();
+ VObject* createObject( const QDomElement & );
+ void createText( VGroup *, const QDomElement & );
+ void parseFont( const QDomElement & );
+ // find object with given id in document
+ VObject* findObject( const QString &name );
+ // find object with given id in given group
+ VObject* findObject( const QString &name, VGroup * );
+
+private:
+ VDocument m_document;
+ QPtrStack<XAMLGraphicsContext> m_gc;
+ QMap<QString, GradientHelper> m_gradients;
+ QMap<QString, QDomElement> m_paths;
+ KoRect m_outerRect;
+};
+
+#endif
diff --git a/filters/karbon/xcf/Makefile.am b/filters/karbon/xcf/Makefile.am
new file mode 100644
index 00000000..83ef8229
--- /dev/null
+++ b/filters/karbon/xcf/Makefile.am
@@ -0,0 +1,27 @@
+kde_module_LTLIBRARIES = libkarbonxcfexport.la
+
+libkarbonxcfexport_la_LDFLAGS = $(KDE_PLUGIN)
+libkarbonxcfexport_la_LIBADD = \
+ $(LIB_KOFFICEUI) \
+ ../../../karbon/libkarboncommon.la
+
+INCLUDES = \
+ $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) \
+ -I$(top_srcdir)/karbon \
+ -I$(top_srcdir)/karbon/core \
+ -I$(top_srcdir)/karbon/render \
+ -I$(top_srcdir)/karbon/visitors \
+ $(all_includes)
+
+service_DATA = karbon_xcf_export.desktop
+servicedir = $(kde_servicesdir)
+
+noinst_HEADERS = \
+ xcfexport.h
+
+libkarbonxcfexport_la_SOURCES = \
+ xcfexport.cc
+
+libkarbonxcfexport_la_METASOURCES = \
+ AUTO
+
diff --git a/filters/karbon/xcf/karbon_xcf_export.desktop b/filters/karbon/xcf/karbon_xcf_export.desktop
new file mode 100644
index 00000000..78772e8e
--- /dev/null
+++ b/filters/karbon/xcf/karbon_xcf_export.desktop
@@ -0,0 +1,65 @@
+[Desktop Entry]
+Icon=
+Name=Karbon14 Gimp Export Filter
+Name[af]=Karbon14 Gimp Voer uit Filter
+Name[ar]=مِرْشَح تصدير Gimp لدى Karbon14
+Name[bg]=Филтър за експортиране от Karbon14 в Gimp
+Name[br]=Sil ezporzh Gimp evit Karbon14
+Name[ca]=Filtre d'exportació Gimp per a Karbon14
+Name[cs]=Exportní filtr do formátu Gimp pro Karbon
+Name[cy]=Hidlen Allforio Gimp Karbon14
+Name[da]=Karbon14 Gimp-eksportfilter
+Name[de]=Karbon14 Gimp-Exportfilter
+Name[el]=Φίλτρο εξαγωγής Gimp του Karbon14
+Name[eo]=Karbon14-Gimp-eksportfiltrilo
+Name[es]=Filtro de exportación Gimp de Karbon14
+Name[et]=Karbon14 Gimp'i ekspordifilter
+Name[eu]=Karbon14-en Gimp esportaziorako iragazkia
+Name[fa]=پالایۀ صادرات Karbon14 Gimp
+Name[fi]=Karbon14 Gimp -vientisuodin
+Name[fr]=Filtre d'exportation Gimp de Karbon 14
+Name[fy]=Gimp-Eksportfilter foar Karbon14
+Name[ga]=Scagaire Easpórtála Gimp Karbon14
+Name[gl]=Filtro de Exportación de Gimp para Karbon14
+Name[he]=מסנן ייצוא מ־Karbon14 ל־Gimp
+Name[hr]=Karbon14 Gimp filtar izvoza
+Name[hu]=Karbon14 Gimp exportszűrő
+Name[is]=Karbon14 Gimp útflutningssía
+Name[it]=Filtro di esportazione Gimp per Karbon14
+Name[ja]=Karbon14 Gimp エクスポートフィルタ
+Name[km]=តម្រង​នាំចេញ Gimp សម្រាប់ Karbon14
+Name[lo]=ຕົວຕອງການສົ່ງອອກ SVG ຂອງ Karbon14
+Name[lt]=Karbon14 Gimp eksportavimo filtras
+Name[lv]=Karbon14 Gimp eksporta filtrs
+Name[ms]=Penapis Eksport Karbon14 Gimp
+Name[nb]=Gimp-eksportfiler for Karbon14
+Name[nds]=Gimp-Exportfilter för Karbon14
+Name[ne]=कार्बन१४ गिम्प निर्यात फिल्टर
+Name[nl]=Gimp-exportfilter voor Karbon14
+Name[nn]=Gimp-eksportfilter for Karbon14
+Name[pl]=Filtr eksportu do formatu Gimpa z Karbon14
+Name[pt]=Filtro de Exportação de Gimp para o Karbon14
+Name[pt_BR]=Filtro de Exportação para o Gimp do Karbon14
+Name[ro]=Filtru exportare Karbon14 pentru Gimp
+Name[ru]=Фильтр экспорта рисунков Karbon14 в формат Gimp
+Name[se]=Karbon14:a Gimp-olggosfievrridansilli
+Name[sk]=GIMP filter pre export z Karbon14
+Name[sl]=Izvozni filter Gimp za Karbon14
+Name[sr]=Karbon14-ов филтер за извоз у Gimp-а
+Name[sr@Latn]=Karbon14-ov filter za izvoz u Gimp-a
+Name[sv]=Karbon14 Gimp-exportfilter
+Name[ta]=Karbon 14 gimp ஏற்றுமதி வடிகட்டி
+Name[tg]=Karbon14 Gimp Филтри Содирот
+Name[tr]=Karbon14 Gimp Aktarma Filtresi
+Name[uk]=Фільтр експорту Gimp для Karbon
+Name[uz]=Karbon14 Gimp eksport filteri
+Name[uz@cyrillic]=Karbon14 Gimp экспорт филтери
+Name[xh]=Isihluzi Sokurhweba ngaphandle se Karbon14 Gimp
+Name[zh_CN]=Karbon14 Gimp 导出过滤器
+Name[zh_TW]=Karbon14 Gimp 匯出過濾程式
+ServiceTypes=KOfficeFilter
+Type=Service
+X-KDE-Export=image/x-xcf-gimp
+X-KDE-Import=application/x-karbon
+X-KDE-Library=libkarbonxcfexport
+X-KDE-Weight=1
diff --git a/filters/karbon/xcf/xcfexport.cc b/filters/karbon/xcf/xcfexport.cc
new file mode 100644
index 00000000..fde8bbd5
--- /dev/null
+++ b/filters/karbon/xcf/xcfexport.cc
@@ -0,0 +1,458 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qcstring.h>
+#include <qdatastream.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kgenericfactory.h>
+#include <KoFilter.h>
+#include <KoFilterChain.h>
+#include <KoStore.h>
+
+#include "vdocument.h"
+#include "vlayer.h"
+#include "xcfexport.h"
+
+#include <kdebug.h>
+
+
+// Tile size constants.
+const unsigned XcfExport::m_tileWidth = 64;
+const unsigned XcfExport::m_tileHeight = 64;
+
+
+typedef KGenericFactory<XcfExport, KoFilter> XcfExportFactory;
+K_EXPORT_COMPONENT_FACTORY( libkarbonxcfexport, XcfExportFactory( "kofficefilters" ) )
+
+
+XcfExport::XcfExport( KoFilter*, const char*, const QStringList& )
+ : KoFilter()
+{
+ m_zoomX = 1.0;
+ m_zoomY = 1.0;
+}
+
+KoFilter::ConversionStatus
+XcfExport::convert( const QCString& from, const QCString& to )
+{
+ if( to != "image/x-xcf-gimp" || from != "application/x-karbon" )
+ {
+ return KoFilter::NotImplemented;
+ }
+
+
+ KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
+
+ if( !storeIn )
+ return KoFilter::StupidError;
+
+
+ QFile fileOut( m_chain->outputFile() );
+
+ if( !fileOut.open( IO_WriteOnly ) )
+ return KoFilter::StupidError;
+
+
+ QDomDocument domIn;
+ domIn.setContent( storeIn );
+ QDomElement docNode = domIn.documentElement();
+
+ m_stream = new QDataStream( &fileOut );
+
+
+ // Load the document.
+ VDocument doc;
+ doc.load( docNode );
+
+ // Process the document.
+ doc.accept( *this );
+
+
+ delete m_stream;
+ fileOut.close();
+
+ return KoFilter::OK;
+}
+
+void
+XcfExport::visitVDocument( VDocument& document )
+{
+ // Offsets.
+ QIODevice::Offset current = 0;
+ QIODevice::Offset start = 0;
+ QIODevice::Offset end = 0;
+
+ // Save width and height for layer saving.
+ m_width = static_cast<unsigned>( document.width() * m_zoomX );
+ m_height = static_cast<unsigned>( document.height() * m_zoomY );
+
+
+ // Header tag (size 14 bytes).
+ m_stream->writeRawBytes( "gimp xcf file", 14 );
+
+ // Image width.
+ *m_stream << static_cast<Q_UINT32>( m_width );
+
+ // Image height.
+ *m_stream << static_cast<Q_UINT32>( m_height );
+
+ // Image type = RGB.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Do not save any properties currently.
+ *m_stream
+ // "END".
+ << static_cast<Q_UINT32>( 0 )
+ // Property size in bytes.
+ << static_cast<Q_UINT32>( 0 );
+
+
+ // Save current offset.
+ current = m_stream->device()->at();
+
+ // Leave space for layer and channel offsets.
+ m_stream->device()->at(
+ // current position + (number layers + number channels + 2) * 4.
+ current + ( document.layers().count() + 3 + 2 ) * 4 );
+
+
+ // Iterate over layers.
+ VLayerListIterator itr( document.layers() );
+
+ for( ; itr.current(); ++itr )
+ {
+ // Save start offset.
+ start = m_stream->device()->at();
+
+
+ // Write layer.
+ itr.current()->accept( *this );
+
+
+ // Save end offset.
+ end = m_stream->device()->at();
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Save layer offset.
+ *m_stream << start;
+
+ // Increment offset.
+ current = m_stream->device()->at();
+
+ // Return to end offset.
+ m_stream->device()->at( end );
+ }
+
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Append a zero offset to indicate end of layer offsets.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+
+ // Return to end offset.
+ m_stream->device()->at( end );
+
+ // Append a zero offset to indicate end of channel offsets.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+}
+
+void
+XcfExport::visitVLayer( VLayer& layer )
+{
+ // Layer width = image width.
+ *m_stream << static_cast<Q_UINT32>( m_width );
+
+ // Layer height = image height.
+ *m_stream << static_cast<Q_UINT32>( m_height );
+
+ // Layer type = RGBA.
+ *m_stream << static_cast<Q_UINT32>( 1 );
+
+ // Layer name.
+ *m_stream << layer.name().latin1();
+
+ // Layer opacity.
+ *m_stream << static_cast<Q_UINT32>( 6 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // Fully opaque = 255.
+ *m_stream << static_cast<Q_UINT32>( 255 );
+
+ // Layer visible?
+ *m_stream << static_cast<Q_UINT32>( 8 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // True.
+ *m_stream << static_cast<Q_UINT32>( 1 );
+
+ // Layer linked?
+ *m_stream << static_cast<Q_UINT32>( 9 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Preserve transparency?
+ *m_stream << static_cast<Q_UINT32>( 10 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Apply mask?
+ *m_stream << static_cast<Q_UINT32>( 11 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Edit mask?
+ *m_stream << static_cast<Q_UINT32>( 12 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Show mask?
+ *m_stream << static_cast<Q_UINT32>( 13 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Layer offsets.
+ *m_stream << static_cast<Q_UINT32>( 15 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 8 );
+ // X-Offset.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+ // Y-Offset.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Layer mode.
+ *m_stream << static_cast<Q_UINT32>( 7 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // Normal mode.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // TODO: Tattoo.
+ *m_stream << static_cast<Q_UINT32>( 20 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 4 );
+ // False.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+ // Layer properties end.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+ // Property size in bytes.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+
+
+ // Offsets.
+ QIODevice::Offset current = 0;
+ QIODevice::Offset start = 0;
+ QIODevice::Offset end = 0;
+
+ // Save current offset.
+ current = m_stream->device()->at();
+
+ // Leave space for hierarchy offsets.
+ m_stream->device()->at( current + 8 );
+
+ // Save start offset.
+ start = m_stream->device()->at();
+
+
+ // Write hierarchy.
+ writeHierarchy();
+
+
+ // Save end offset.
+ end = m_stream->device()->at();
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Save hierarchy offset.
+ *m_stream << start;
+
+
+ // Append a zero offset to indicate end of layer mask offsets.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+}
+
+void
+XcfExport::writeHierarchy()
+{
+ // Offsets.
+ QIODevice::Offset current = 0;
+ QIODevice::Offset start = 0;
+ QIODevice::Offset end = 0;
+
+ // Width (again?).
+ *m_stream << m_width;
+
+ // Height (again?).
+ *m_stream << m_height;
+
+ // Color depth.
+ *m_stream << static_cast<Q_UINT32>( 3 );
+
+
+ // Calculate level number.
+ int levX = levels( m_width, m_tileWidth );
+ int levY = levels( m_height, m_tileHeight );
+ int levels = QMAX( levX, levY );
+
+ int width = m_width;
+ int height = m_height;
+
+ // Save current offset.
+ current = m_stream->device()->at();
+
+ // Leave space for level offsets.
+ m_stream->device()->at( current + ( levels + 1 ) * 4 );
+
+ for( int i = 0; i < levels; ++i )
+ {
+ // Save start offset.
+ start = m_stream->device()->at();
+
+ if( i == 0 )
+ {
+ // Write level.
+ writeLevel();
+ }
+ else
+ {
+ // Fake an empty level.
+ width /= 2;
+ height /= 2;
+
+ *m_stream << static_cast<Q_UINT32>( width );
+ *m_stream << static_cast<Q_UINT32>( height );
+ *m_stream << static_cast<Q_UINT32>( 0 );
+ }
+
+ // Save end offset.
+ end = m_stream->device()->at();
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Save level offset.
+ *m_stream << start;
+
+ // Increment offset.
+ current = m_stream->device()->at();
+
+ // Return to end offset.
+ m_stream->device()->at( end );
+ }
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Append a zero offset to indicate end of level offsets.
+ *m_stream << static_cast<Q_UINT32>( 0 );
+}
+
+void
+XcfExport::writeLevel()
+{
+ // Offsets.
+ QIODevice::Offset current = 0;
+ QIODevice::Offset start = 0;
+ QIODevice::Offset end = 0;
+
+ *m_stream << static_cast<Q_UINT32>( m_width );
+ *m_stream << static_cast<Q_UINT32>( m_height );
+
+ int rows = ( m_height + m_tileHeight - 1 ) / m_tileHeight;
+ int cols = ( m_width + m_tileWidth - 1 ) / m_tileWidth;
+ int tiles = rows * cols;
+
+ // Save current offset.
+ current = m_stream->device()->at();
+
+ // Leave space for tile offsets.
+ m_stream->device()->at( current + ( tiles + 1 ) * 4 );
+
+ for( int i = 0; i < tiles; ++i )
+ {
+ // Save start offset.
+ start = m_stream->device()->at();
+
+
+ // TODO: Save tile.
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+ *m_stream << static_cast<Q_UINT8>( 1 );
+
+
+ // Save end offset.
+ end = m_stream->device()->at();
+
+ // Return to current offset.
+ m_stream->device()->at( current );
+
+ // Save tile offset.
+ *m_stream << start;
+
+ // Increment offset.
+ current = m_stream->device()->at();
+
+ // Return to end offset.
+ m_stream->device()->at( end );
+ }
+}
+
+int
+XcfExport::levels( int layerSize, int tileSize )
+{
+ int l = 1;
+
+ while( layerSize > tileSize )
+ {
+ layerSize /= 2;
+ l += 1;
+ }
+
+ return l;
+}
+
+#include "xcfexport.moc"
diff --git a/filters/karbon/xcf/xcfexport.h b/filters/karbon/xcf/xcfexport.h
new file mode 100644
index 00000000..92913cb4
--- /dev/null
+++ b/filters/karbon/xcf/xcfexport.h
@@ -0,0 +1,97 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, The Karbon Developers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __XCFEXPORT_H__
+#define __XCFEXPORT_H__
+
+
+#include <KoFilter.h>
+
+#include "vvisitor.h"
+
+
+class QDataStream;
+class VDocument;
+class VLayer;
+
+
+class XcfExport : public KoFilter, private VVisitor
+{
+ Q_OBJECT
+
+public:
+ XcfExport( KoFilter* parent, const char* name, const QStringList& );
+ virtual ~XcfExport() {}
+
+ virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to );
+
+ virtual void visitVDocument( VDocument& document );
+ virtual void visitVLayer( VLayer& layer );
+
+private:
+ /**
+ * Writes a hierarchy.
+ */
+ void writeHierarchy();
+
+ /**
+ * Writes a level.
+ */
+ void writeLevel();
+
+ /**
+ * Calculates levels from layer and tile size.
+ */
+ static int levels( int layerSize, int tileSize );
+
+
+ /**
+ * Tile size constants.
+ */
+ static const unsigned m_tileWidth;
+ static const unsigned m_tileHeight;
+
+ /**
+ * Output stream.
+ */
+ QDataStream* m_stream;
+
+ /**
+ * Image width.
+ */
+ unsigned m_width;
+
+ /**
+ * Image height.
+ */
+ unsigned m_height;
+
+ /**
+ * X-zoom factor.
+ */
+ double m_zoomX;
+
+ /**
+ * Y-zoom factor.
+ */
+ double m_zoomY;
+};
+
+#endif
+
diff --git a/filters/karbon/xfig/karbon_xfig_import.desktop b/filters/karbon/xfig/karbon_xfig_import.desktop
new file mode 100644
index 00000000..227854c1
--- /dev/null
+++ b/filters/karbon/xfig/karbon_xfig_import.desktop
@@ -0,0 +1,61 @@
+[Desktop Entry]
+Type=Service
+Name=Karbon XFig Import Filter
+Name[ar]=مِرْشَح استيراد XFig لدى Karbon
+Name[bg]=Филтър за импортиране от XFig в Karbon
+Name[br]=Sil enporzh XFig evit Karbon
+Name[ca]=Filtre d'importació XFig per a Karbon
+Name[cs]=Importní filtr Xfig pro Karbon
+Name[cy]=Hidlen Fewnforio XFig Karbon
+Name[da]=Karbon XFig-importfilter
+Name[de]=Karbon14 XFig-Importfilter
+Name[el]=Φίλτρο εισαγωγής XFig του Karbon
+Name[eo]=Karbon-XFig-importfiltrilo
+Name[es]=Filtro de importación XFig de Karbon
+Name[et]=Karboni XFig'i impordifilter
+Name[eu]=Karbon14-en XFig esportaziorako iragazkia
+Name[fa]=پالایۀ واردات Karbon XFig
+Name[fi]=Karbon XFig -tuontisuodin
+Name[fr]=Filtre d'importation XFig de Karbon 14
+Name[fy]=Xfig-Ymportfilter foar Karbon
+Name[ga]=Scagaire Iompórtála Karbon XFig
+Name[gl]=Filtro de Importación de XFig para Karbon
+Name[he]=מסנן ייבוא מ־XFig ל־Karbon
+Name[hr]=Karbon XFig filtar uvoza
+Name[hu]=Karbon XFig importszűrő
+Name[is]=Karbon XFig innflutningssía
+Name[it]=Filtro di importazione XFig per Karbon
+Name[ja]=Karbon XFig インポートフィルタ
+Name[km]=តម្រង​នាំចូល XFig សម្រាប់ Karbon
+Name[lt]=Karbon XFig importavimo filtras
+Name[lv]=Karbon XFig importa filtrs
+Name[ms]=Penapis Import Karbon XFig
+Name[nb]=XFig-importfilter for Karbon
+Name[nds]=XFig-Importfilter för Karbon14
+Name[ne]=कार्बन एक्सआकृति निर्यात फिल्टर
+Name[nl]=Xfig-importfilter voor Karbon
+Name[nn]=XFig-importfilter for Karbon
+Name[pl]=Filtr importu formatu XFig do Karbon
+Name[pt]=Filtro de Importação de XFig para o Karbon
+Name[pt_BR]=Filtro de Importação XFig do Karbon
+Name[ro]=Filtru importare Karbon14 pentru XFig
+Name[ru]=Фильтр импорта рисунков XFig в Karbon
+Name[se]=Karbon:a XFig-sisafievrridansilli
+Name[sk]=XFig filter pre import pre Karbon
+Name[sl]=Uvozni filter XFig za Karbon
+Name[sr]=Karbon-ов филтер за увоз из XFig-а
+Name[sr@Latn]=Karbon-ov filter za uvoz iz XFig-a
+Name[sv]=Karbon Xfig-importfilter
+Name[ta]=karbon xfig இறக்குமதி வடிகட்டி
+Name[tg]=Karbon XFig Филтри Воридот
+Name[tr]=Karbon XFig Alma Filtresi
+Name[uk]=Фільтр імпорту XFig для Karbon
+Name[uz]=Karbon XFig import filteri
+Name[uz@cyrillic]=Karbon XFig импорт филтери
+Name[zh_CN]=Karbon XFig 导入过滤器
+Name[zh_TW]=Karbon XFig 匯入過濾程式
+X-KDE-Export=application/x-karbon
+X-KDE-Import=image/x-xfig
+X-KDE-Weight=1
+X-KDE-Library=libxfigimport
+ServiceTypes=KOfficeFilter
diff --git a/filters/karbon/xfig/status.html b/filters/karbon/xfig/status.html
new file mode 100644
index 00000000..e86ff8d9
--- /dev/null
+++ b/filters/karbon/xfig/status.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>KOffice filters status: XFig FILTER</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666">
+<A NAME="START">&nbsp;</A>
+
+<BR>
+<center>
+ <h1>
+ KOffice filters status: &nbsp;&nbsp;<i>XFig FILTER</i>
+ </h1>
+</center>
+
+<hr NOSHADE SIZE="2" WIDTH="70%">
+
+<font size="-1"><b>
+ <A HREF="#import">Import</A> |
+ <A HREF="#export">Export</A>
+</b></font>
+
+<BR><BR><BR>
+<center><a NAME="import"></a></center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER="0" CELLSPACING="0" BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER="0" CELLPADDING="2" BGCOLOR="#FFFFFF" WIDTH="100%">
+
+ <tr BGCOLOR="#DDFFDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>
+ Import XFig for karbon<BR>
+ <BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP" WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN="TOP"><b><font size="+1">Features</font></b></td>
+ <td>- Can import XFig documents.</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Todo</font></b></td>
+ <td>Needs to be ported from kontour to karbon libs.</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">History</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Authors&nbsp;</font></b></td>
+ <td><a href="mailto:buis@kde.org">-</a></td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Links</font></b></td>
+ <td><a href="http://www.koffice.org">-</a></td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td>
+ <td>---</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+<br><br><br>
+
+<hr NOSHADE SIZE=1>
+<br><br><br>
+
+
+<center>
+ <a NAME="export"></a>
+</center>
+
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+<center>
+<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%">
+ <tr>
+ <td>
+ <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%">
+ <tr BGCOLOR="#FFDDDD">
+ <td COLSPAN="2">
+ <center><b><i><font size="+1">
+ <BR>Export karbon file to XFig<BR><BR>
+ </font></i></b></center>
+ </td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN="TOP" WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Features</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Todo</font></b></td>
+ <td>Everything</td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">History</font></b></td>
+ <td>-</td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Authors</font></b></td>
+ <td><a href="mailto:buis@kde.org">-</a></td>
+ </tr>
+
+ <tr BGCOLOR="#CCCCFF">
+ <td VALIGN=TOP><b><font size="+1">Links</font></b></td>
+ <td><!-- <a href="http://www.koffice.org">-</a>--></td>
+ </tr>
+
+ <tr BGCOLOR="#EEEEFF">
+ <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td>
+ <td>-</td>
+ </tr>
+
+
+
+ </table>
+ </td>
+ </tr>
+</table>
+</center>
+<A HREF="#START"><font size="-1"><b>Up</b></font></A>
+
+<br>
+<br><br><br><br><br><br><br>
+
+</body>
+</html>
diff --git a/filters/karbon/xfig/xfigimport.cc b/filters/karbon/xfig/xfigimport.cc
new file mode 100644
index 00000000..06301e01
--- /dev/null
+++ b/filters/karbon/xfig/xfigimport.cc
@@ -0,0 +1,760 @@
+/*
+ Copyright (C) 1998 Kai-Uwe Sattler <kus@iti.cs.uni-magdeburg.de>
+ Copyright (C) 2001, Rob Buis <rwlbuis@wanadoo.nl>
+ Copyright (C) 2003, Rob Buis <buis@kde.org>
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#include <assert.h>
+#include <fstream.h>
+#include <limits.h>
+#include <math.h>
+
+#include <GDocument.h>
+#include <GPage.h>
+#include <GGroup.h>
+#include <GPolyline.h>
+#include <GOval.h>
+#include <GPolygon.h>
+#include <GText.h>
+#include <xfigimport.h>
+#include <xfigimport.moc>
+
+#include <qtl.h>
+#include <kdebug.h>
+
+#include <core/vdocument.h>
+namespace std { };
+using namespace std;
+
+#define RAD_FACTOR 180.0 / M_PI
+
+unsigned int colors[] = {
+ 0x000090,
+ 0x0000b0,
+ 0x0000d0,
+ 0x87ceff,
+ 0x009000,
+ 0x00b000,
+ 0x00d000,
+ 0x009090,
+ 0x00b0b0,
+ 0x00d0d0,
+ 0x900000,
+ 0xb00000,
+ 0xd00000,
+ 0x900090,
+ 0xb000b0,
+ 0xd000d0,
+ 0x803000,
+ 0xa04000,
+ 0xc06000,
+ 0xff8080,
+ 0xffa0a0,
+ 0xffc0c0,
+ 0xffe0e0,
+ 0xffd700
+};
+
+int arrow_ids[] = {
+ 6, 1, 2, 7
+};
+
+struct PSFont {
+ const char* family;
+ QFont::Weight weight;
+ bool italic;
+} psFontTable[] = {
+ { "times", QFont::Normal, false }, // Times Roman
+ { "times", QFont::Normal, true }, // Times Italic
+ { "times", QFont::Bold, false }, // Times Bold
+ { "times", QFont::Bold, true }, // Times Bold Italic
+ { "avantgarde", QFont::Normal, false }, // AvantGarde Book
+ { "avantgarde", QFont::Normal, true }, // AvantGarde Book Oblique
+ { "avantgarde", QFont::DemiBold, false }, // AvantGarde Demi
+ { "avantgarde", QFont::DemiBold, true }, // AvantGarde Demi Oblique
+ { "bookman", QFont::Light, false }, // Bookman Light
+ { "bookman", QFont::Light, true }, // Bookman Light Italic
+ { "bookman", QFont::DemiBold, false }, // Bookman Demi
+ { "bookman", QFont::DemiBold, true }, // Bookman Demi Italic
+ { "courier", QFont::Normal, false }, // Courier
+ { "courier", QFont::Normal, true }, // Courier Oblique
+ { "courier", QFont::Bold, false }, // Courier Bold
+ { "courier", QFont::Bold, true }, // Courier Bold Oblique
+ { "helvetica", QFont::Normal, false }, // Helvetica
+ { "helvetica", QFont::Normal, true }, // Helvetica Oblique
+ { "helvetica", QFont::Bold, false }, // Helvetica Bold
+ { "helvetica", QFont::Bold, true }, // Helvetica Bold Oblique
+ { "helvetica", QFont::Normal, false }, // Helvetica Narrow
+ { "helvetica", QFont::Normal, true }, // Helvetica Narrow Oblique
+ { "helvetica", QFont::Bold, false }, // Helvetica Narrow Bold
+ { "helvetica", QFont::Bold, true }, // Helvetica Narrow Bold Oblique
+ { "newcenturyschoolbook", QFont::Normal, false },// New Century Schoolbook
+ { "newcenturyschoolbook", QFont::Normal, true }, // New Century Italic
+ { "newcenturyschoolbook", QFont::Bold, false }, // New Century Bold
+ { "newcenturyschoolbook", QFont::Bold, true }, // New Century Bold Italic
+ { "palatino", QFont::Normal, false }, // Palatino Roman
+ { "palatino", QFont::Normal, true }, // Palatino Italic
+ { "palatino", QFont::Bold, false }, // Palatino Bold
+ { "palatino", QFont::Bold, true }, // Palatino Bold Italic
+ { "symbol", QFont::Normal, false }, // Symbol
+ { "zapfchancery", QFont::Normal, false }, // Zapf Chancery Medium Italic
+ { "zapfdingbats", QFont::Normal, false }, // Zapf Dingbats
+};
+
+int hexstrToInt (const char *str) {
+ const int fak[] = { 16, 1 };
+ int value = 0, v;
+
+ for (int i = 0; i < 2; i++) {
+ if (str[i] >= '0' && str[i] <= '9')
+ v = str[i] - '0';
+ else
+ v = str[i] - 'a' + 10;
+ value += v * fak[i];
+ }
+
+ return value;
+}
+
+XFIGImport::XFIGImport( KoFilter *parent, const char *name ) : KoFilter(parent, name)
+{
+ fig_resolution = 1200.0 / 72.0;
+ coordinate_system = 2;
+
+ colorTable.insert (0, new QColor (Qt::black));
+ colorTable.insert (1, new QColor (Qt::blue));
+ colorTable.insert (2, new QColor (Qt::green));
+ colorTable.insert (3, new QColor (Qt::cyan));
+ colorTable.insert (4, new QColor (Qt::red));
+ colorTable.insert (5, new QColor (Qt::magenta));
+ colorTable.insert (6, new QColor (Qt::yellow));
+ colorTable.insert (7, new QColor (Qt::white));
+
+ for (int i = 0; i <= 23; i++)
+ colorTable.insert (i + 8, new QColor (colors[i]));
+
+ objList.clear ();
+}
+
+XFIGImport::~XFIGImport()
+{
+}
+
+bool XFIGImport::filterImport( const QString &file, KoDocument *doc,
+ const QString &from, const QString &to,
+ const QString & ) {
+
+ if( to != "application/x-karbon" || from != "image/x-xfig" )
+ return false;
+
+ char buf[255];
+ int value;
+ KoPageLayout layout;
+
+ ifstream fin( file.local8Bit() );
+ if (! fin)
+ return false;
+
+ KIllustratorDocument *kidoc = (KIllustratorDocument *) doc;
+ GDocument *gdoc = kidoc->gdoc();
+ //GPage *activePage = gdoc->activePage();
+
+ layout = gdoc->activePage()->pageLayout ();
+
+ fin.getline (buf, 255);
+ if (::strncmp (buf, "#FIG 3", 6)) {
+ kdDebug() << "ERROR: no xfig file or wrong header" << endl;
+ return false;
+ }
+
+ if (buf[7] == '2') {
+ version = 320;
+ }
+ else if (buf[7] == '1') {
+ version = 310;
+ }
+ else {
+ kdDebug() << "ERROR: unsupported xfig version" << endl;
+ return false;
+ }
+
+ /*
+ * read the header
+ */
+
+ // orientation
+ fin.getline (buf, 255);
+ if (::strcmp (buf, "Landscape") == 0)
+ layout.orientation = PG_LANDSCAPE;
+ else if (::strcmp (buf, "Portrait") == 0)
+ layout.orientation = PG_PORTRAIT;
+ else
+ kdDebug() << "ERROR: invalid orientation" << endl;
+
+ // justification (don't know how to handle this)
+ fin.getline (buf, 255);
+
+ // units
+ fin.getline (buf, 255);
+ if (::strcmp (buf, "Metric") == 0)
+ layout.unit = PG_MM;
+ else if (::strcmp (buf, "Inches") == 0)
+ layout.unit = PG_INCH;
+ else
+ kdDebug() << "ERROR: invalid units" << endl;
+
+ if (version >= 320) {
+ // paper size (don't know how to handle this)
+ fin.getline (buf, 255);
+
+ // magnification
+ float magnification;
+ fin >> magnification;
+ fin.ignore (INT_MAX, '\n');
+
+ //multiple page (not supported yet)
+ fin.getline (buf, 255);
+
+ // transparent color (not supported yet)
+ int transColor;
+ fin >> transColor;
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ // resolution and coordinate system
+ fin >> value >> coordinate_system;
+ fig_resolution = value / 72.0;
+ fin.ignore (INT_MAX, '\n');
+
+ // now read in the objects
+ while (! fin.eof ()) {
+ int tag = -1;
+ fin >> tag;
+ if (tag == -1) {
+ // EOF
+ buildDocument (gdoc);
+ return true;
+ }
+
+ switch (tag) {
+ case 0:
+ // a color pseudo object
+ parseColorObject (fin);
+ break;
+ case 1:
+ // a ellipse
+ parseEllipse (fin, gdoc);
+ break;
+ case 2:
+ // a polyline
+ parsePolyline (fin, gdoc);
+ break;
+ case 3:
+ // a spline
+ parseSpline (fin, gdoc);
+ break;
+ case 4:
+ // a text
+ parseText (fin, gdoc);
+ break;
+ case 5:
+ // an arc
+ parseArc (fin, gdoc);
+ break;
+ case 6:
+ // a compound object
+ parseCompoundObject (fin, gdoc);
+ break;
+ case -6:
+ // end of compound object --> ignore it
+ break;
+ default:
+ // should not occur
+ kdDebug() << "unknown object type: " << tag << endl;
+ break;
+ }
+ }
+ buildDocument (gdoc);
+ return true;
+}
+
+
+void XFIGImport::parseColorObject (istream& fin) {
+ int number, red, green, blue;
+ char buf[20], red_str[3], green_str[3], blue_str[3];
+
+ fin >> number >> buf;
+ strncpy (red_str, &buf[1], 2); red_str[2] = '\0';
+ strncpy (green_str, &buf[3], 2); green_str[2] = '\0';
+ strncpy (blue_str, &buf[5], 2); blue_str[2] = '\0';
+
+ red = hexstrToInt (red_str);
+ green = hexstrToInt (green_str);
+ blue = hexstrToInt (blue_str);
+
+ colorTable.insert (number, new QColor (red, green, blue));
+}
+
+void XFIGImport::parseArc (istream& fin, GDocument* doc) {
+ int sub_type, line_style, thickness, pen_color, fill_color,
+ depth, pen_style, area_fill, cap_style, direction,
+ forward_arrow, backward_arrow, x1, y1, x2, y2, x3, y3;
+ float center_x, center_y;
+ float style_val;
+ GOval *obj = new GOval (doc);
+
+ // first line
+ fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
+ >> depth >> pen_style >> area_fill >> style_val >> cap_style
+ >> direction >> forward_arrow >> backward_arrow
+ >> center_x >> center_y >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
+
+ if (forward_arrow > 0) {
+ // forward arow line
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ if (backward_arrow > 0) {
+ // backward arrow line
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ // compute radius
+ float dx = x1 - center_x;
+ float dy = y1 - center_y;
+ float radius = sqrt (dx * dx + dy * dy);
+
+ if (radius==0) {
+ delete obj;
+ return;
+ }
+
+ Coord p1 ((center_x - radius) / fig_resolution,
+ (center_y - radius) / fig_resolution);
+ Coord p2 ((center_x + radius) / fig_resolution,
+ (center_y + radius) / fig_resolution);
+
+ obj->setStartPoint (p1);
+ obj->setEndPoint (p2);
+
+ if (sub_type == 0)
+ obj->setOutlineShape (GObject::OutlineInfo::PieShape);
+ else if (sub_type == 1)
+ obj->setOutlineShape (GObject::OutlineInfo::ArcShape);
+
+ p1 = Coord (center_x / fig_resolution, center_y /fig_resolution);
+ float m;
+
+ float angle1;
+ p2 = Coord (x1 / fig_resolution, y1 /fig_resolution);
+ if (p2.x () == p1.x ()) {
+ if (p2.y () > p1.y ())
+ angle1 = 90;
+ else
+ angle1 = -90;
+ }
+ else {
+ m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
+ if ( p2.x () > p1.x ())
+ angle1 = atan (m) * RAD_FACTOR;
+ else
+ angle1 = 180 + atan (m) * RAD_FACTOR;
+ }
+
+ float angle2;
+ p2 = Coord (x3 / fig_resolution, y3 /fig_resolution);
+ if (p2.x () == p1.x ()) {
+ if (p2.y () > p1.y ())
+ angle2 = 90;
+ else
+ angle2 = -90;
+ }
+ else {
+ m = ((p2.y () - p1.y ()) / (p2.x () - p1.x ()));
+ if ( p2.x () > p1.x ())
+ angle2 = atan (m) * RAD_FACTOR;
+ else
+ angle2 = 180 + atan (m) * RAD_FACTOR;
+ }
+
+ if (direction==0) // clockwise
+ obj->setAngles (angle2, angle1);
+ else if (direction==1) // counterclockwise
+ obj->setAngles (angle1, angle2);
+
+ // now set the properties
+ setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);
+ objList.append( GObjectListItem( depth, obj ) );
+}
+
+void XFIGImport::parseEllipse (istream& fin, GDocument* doc) {
+ int sub_type, line_style, thickness, pen_color, fill_color,
+ depth, pen_style, area_fill, direction, center_x, center_y,
+ radius_x, radius_y, start_x, start_y, end_x, end_y;
+ float style_val, angle;
+ GOval *obj = new GOval (doc);
+
+ // first line
+ fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
+ >> depth >> pen_style >> area_fill >> style_val >> direction
+ >> angle >> center_x >> center_y >> radius_x >> radius_y
+ >> start_x >> start_y >> end_x >> end_y;
+ Coord p1, p2;
+
+ p1 = Coord ((center_x - radius_x) /fig_resolution,
+ (center_y - radius_y) /fig_resolution);
+ p2 = Coord ((center_x + radius_x) /fig_resolution,
+ (center_y + radius_y) /fig_resolution);
+
+ obj->setStartPoint (p1);
+ obj->setEndPoint (p2);
+
+ // now set the properties
+ setProperties (obj, pen_color, pen_style, thickness, area_fill, fill_color);
+ objList.append( GObjectListItem( depth, obj ) );
+}
+
+void XFIGImport::parsePolyline (istream& fin, GDocument* doc) {
+ int sub_type, line_style, thickness, pen_color, fill_color,
+ depth, pen_style, area_fill, join_style, cap_style, radius,
+ forward_arrow, backward_arrow, npoints;
+ float style_val;
+ GPolyline *obj = NULL;
+
+ // first line
+ fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
+ >> depth >> pen_style >> area_fill >> style_val >> join_style
+ >> cap_style >> radius >> forward_arrow >> backward_arrow
+ >> npoints;
+ fin.ignore (INT_MAX, '\n');
+
+ switch (sub_type) {
+ case 1: // polyline
+ obj = new GPolyline (doc);
+ break;
+ case 2: // box
+ obj = new GPolygon (doc);
+ break;
+ case 3: // polygon
+ obj = new GPolygon (doc);
+ break;
+ case 4: // arc-box
+ obj = new GPolygon (doc);
+ break;
+ case 5: // imported picture
+ return;
+ break;
+ default:
+ // doesn't occur
+ kdDebug() << "unknown subtype: " << sub_type << endl;
+ break;
+ }
+
+ assert (obj != NULL);
+
+ int arrow_type, arrow_style;
+ float arrow_thickness, arrow_width, arrow_height;
+ GObject::OutlineInfo oinfo;
+ oinfo.mask = GObject::OutlineInfo::Custom;
+ oinfo.startArrowId = oinfo.endArrowId = 0;
+
+ if (forward_arrow > 0) {
+
+ // forward arrow line
+ fin >> arrow_type >> arrow_style >> arrow_thickness
+ >> arrow_width >> arrow_height;
+ oinfo.endArrowId = arrow_ids[arrow_type];
+ if (oinfo.endArrowId == 1 && arrow_style == 0)
+ oinfo.endArrowId = 4;
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ if (backward_arrow > 0) {
+ // backward arrow line
+ fin >> arrow_type >> arrow_style >> arrow_thickness
+ >> arrow_width >> arrow_height;
+ oinfo.startArrowId = arrow_ids[arrow_type];
+ if (oinfo.startArrowId == 1 && arrow_style == 0)
+ oinfo.startArrowId = 4;
+ fin.ignore (INT_MAX, '\n');
+ }
+ // points line
+ for (int i = 0; i < npoints; i++) {
+ int x, y;
+ fin >> x >> y;
+ if ((sub_type == 2 || sub_type == 3) && i == npoints -1)
+ // first point == last point
+ break;
+
+ Coord p (x / fig_resolution, y / fig_resolution);
+ obj->_addPoint (i, p);
+ }
+
+ if (oinfo.startArrowId || oinfo.endArrowId)
+ obj->setOutlineInfo (oinfo);
+
+ // now set the properties
+ setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);
+
+ // and insert the object
+ objList.append( GObjectListItem( depth, obj ) );
+}
+
+void XFIGImport::parseSpline (istream& fin, GDocument* doc)
+{
+ int sub_type, line_style, thickness, pen_color, fill_color, depth,
+ pen_style, area_fill, cap_style, forward_arrow, backward_arrow, npoints;
+ float style_val;
+
+ // this should be a spline
+ GPolyline *obj = 0L;
+ fin >> sub_type >> line_style >> thickness >> pen_color >> fill_color
+ >> depth >> pen_style >> area_fill >> style_val >> cap_style
+ >> forward_arrow >> backward_arrow >> npoints;
+ if (sub_type == 1 || sub_type == 3 || sub_type == 5)
+ obj = new GPolygon (doc);
+ else
+ obj = new GPolyline (doc);
+
+ int arrow_type, arrow_style;
+ float arrow_thickness, arrow_width, arrow_height;
+ GObject::OutlineInfo oinfo;
+ oinfo.mask = GObject::OutlineInfo::Custom;
+ oinfo.startArrowId = oinfo.endArrowId = 0;
+
+ if (forward_arrow > 0) {
+
+ // forward arrow line
+ fin >> arrow_type >> arrow_style >> arrow_thickness
+ >> arrow_width >> arrow_height;
+ oinfo.endArrowId = arrow_ids[arrow_type];
+ if (oinfo.endArrowId == 1 && arrow_style == 0)
+ oinfo.endArrowId = 4;
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ if (backward_arrow > 0) {
+ // backward arrow line
+ fin >> arrow_type >> arrow_style >> arrow_thickness
+ >> arrow_width >> arrow_height;
+ oinfo.startArrowId = arrow_ids[arrow_type];
+ if (oinfo.startArrowId == 1 && arrow_style == 0)
+ oinfo.startArrowId = 4;
+ fin.ignore (INT_MAX, '\n');
+ }
+
+ // points line
+ for (int i = 0; i < npoints; i++) {
+ int x, y;
+ fin >> x >> y;
+ if ((sub_type == 1 || sub_type == 3 || sub_type == 5) && i == npoints -1)
+ // first point == last point
+ break;
+
+ Coord p (x / fig_resolution, y / fig_resolution);
+ obj->_addPoint (i, p);
+ }
+
+ // control points line
+ for (int i = 0; i < npoints; i++) {
+ float fac;
+ fin >> fac;
+ // ignore it now
+ // fin.ignore (INT_MAX, '\n');
+ }
+
+ if (oinfo.startArrowId || oinfo.endArrowId)
+ obj->setOutlineInfo (oinfo);
+
+ // now set the properties
+ setProperties (obj, pen_color, line_style, thickness, area_fill, fill_color);
+
+ // and insert the object
+ objList.append( GObjectListItem( depth, obj ) );
+}
+
+void XFIGImport::parseText (istream& fin, GDocument* doc)
+{
+ int sub_type, color, depth, pen_style, font, font_flags, x, y;
+ float font_size, angle, height, length;
+ GText *obj = new GText (doc);
+ char c;
+ char ocode[4];
+ bool finished = false;
+ QString text;
+ QFont qfont;
+
+ fin >> sub_type >> color >> depth >> pen_style >> font >> font_size
+ >> angle >> font_flags >> height >> length >> x >> y;
+
+ if (font_flags & 4) {
+ // PostScript font
+ if (font == -1)
+ font = 0;
+ qfont = QFont (psFontTable[font].family, qRound (font_size),
+ psFontTable[font].weight, psFontTable[font].italic);
+ }
+ else {
+ // LaTeX font
+ switch (font) {
+ case 1: // Roman
+ qfont.setFamily ("times");
+ break;
+ case 2: // Bold
+ qfont.setBold (true);
+ break;
+ case 3: // Italic
+ qfont.setItalic (true);
+ break;
+ case 4: // Sans Serif
+ qfont.setFamily ("helvetica");
+ break;
+ case 5: // Typewriter
+ qfont.setFamily ("Courier");
+ break;
+ default:
+ break;
+ }
+ }
+ qfont.setPointSize (qRound (font_size));
+ obj->setFont (qfont);
+
+ while (! finished) {
+ fin.get (c);
+ if (c == '\\') {
+ fin.get (ocode, 4);
+ int code = (ocode[0] - '0') * 64 +
+ (ocode[1] - '0') * 8 +
+ (ocode[2] - '0');
+ if (code == 1)
+ finished = true;
+ else
+ text += (char) code;
+ }
+ else
+ text += c;
+ }
+ obj->setText (text);
+
+ if (sub_type == 1) {
+ GText::TextInfo ti = obj->getTextInfo ();
+ ti.align = GText::TextInfo::AlignCenter;
+ obj->setTextInfo (ti);
+ }
+ else if (sub_type == 2) {
+ GText::TextInfo ti = obj->getTextInfo ();
+ ti.align = GText::TextInfo::AlignRight;
+ obj->setTextInfo (ti);
+ }
+ Coord origin (x / fig_resolution, y / fig_resolution - qfont.pointSize ());
+ obj->setOrigin (origin);
+
+ if (angle != 0) {
+ // rotate the text
+ float nangle = angle * RAD_FACTOR;
+ QWMatrix m1, m2, m3;
+ Coord rotCenter;
+
+ if (sub_type == 0) {
+ rotCenter = Coord (obj->boundingBox ().left (),
+ obj->boundingBox ().bottom ());
+ }
+ else if (sub_type == 1) {
+ rotCenter = Coord (obj->boundingBox ().width () / 2,
+ obj->boundingBox ().bottom ());
+ }
+ else if (sub_type == 2) {
+ rotCenter = Coord (obj->boundingBox ().right (),
+ obj->boundingBox ().bottom ());
+ }
+ m1.translate (-rotCenter.x (), -rotCenter.y ());
+ m2.rotate (-nangle);
+ m3.translate (rotCenter.x (), rotCenter.y ());
+ obj->transform (m1);
+ obj->transform (m2);
+ obj->transform (m3, true);
+ }
+
+ objList.append( GObjectListItem( depth, obj ) );
+}
+
+void XFIGImport::parseCompoundObject (istream& fin, GDocument* /*doc*/) {
+ int upperright_x, upperright_y, lowerleft_x, lowerleft_y;
+
+ fin >> upperright_x >> upperright_y >> lowerleft_x >> lowerleft_y;
+ fin.ignore (INT_MAX, '\n');
+}
+
+
+/**
+ * Copy all parsed objects from the sorted list to the document.
+ */
+void XFIGImport::buildDocument (GDocument *doc) {
+ doc->setAutoUpdate (false);
+ // This will sort all object, by decreasing depth
+ qBubbleSort(objList);
+
+ // Now all we need to do is insert them in the document, in that order
+ QValueList<GObjectListItem>::Iterator it=objList.begin();
+ for ( ; it != objList.end() ; ++it )
+ {
+ //kdDebug() << "Inserting object with depth=" << (*it).depth << endl;
+ GObject* obj = (*it).object;
+ obj->ref ();
+ doc->activePage()->insertObject (obj);
+ }
+ doc->setAutoUpdate (true);
+ objList.clear(); // save memory
+}
+
+void XFIGImport::setProperties (GObject* obj, int pen_color, int style,
+ int thickness, int area_fill, int fill_color) {
+ if (pen_color >= 0)
+ obj->setOutlineColor (*colorTable[pen_color]);
+
+ if (style < 1)
+ obj->setOutlineStyle (Qt::SolidLine);
+ else if (style == 1)
+ obj->setOutlineStyle (Qt::DashLine);
+ else if (style == 2)
+ obj->setOutlineStyle (Qt::DotLine);
+
+ obj->setOutlineWidth (thickness * 72.0 / 80.0);
+
+ if (area_fill == -1)
+ obj->setFillStyle (GObject::FillInfo::NoFill);
+ else {
+ obj->setFillStyle (GObject::FillInfo::SolidFill);
+ if (fill_color < 1) {
+ // for BLACK or DEFAULT color
+ int val = qRound ((20 - area_fill) * 255.0 / 20.0);
+ obj->setFillColor (QColor (val, val, val));
+ }
+ else if (fill_color == 7) {
+ // for WHITE color
+ int val = qRound ( area_fill * 255.0 / 20.0);
+ obj->setFillColor (QColor (val, val, val));
+ }
+ else
+ obj->setFillColor (*colorTable[fill_color]);
+ }
+}
+
diff --git a/filters/karbon/xfig/xfigimport.h b/filters/karbon/xfig/xfigimport.h
new file mode 100644
index 00000000..bf959315
--- /dev/null
+++ b/filters/karbon/xfig/xfigimport.h
@@ -0,0 +1,94 @@
+/*
+ Copyright (C) 1998 Kai-Uwe Sattler <kus@iti.cs.uni-magdeburg.de>
+ Copyright (C) 2001, Rob Buis <rwlbuis@wanadoo.nl>
+ Copyright (C) 2003, Rob Buis <buis@kde.org>
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#ifndef XFIGIMPORT_H
+#define XFIGIMPORT_H
+
+#include <qintdict.h>
+#include <qvaluelist.h>
+#include <iostream.h>
+
+class GDocument;
+class GObject;
+class QColor;
+
+#include <KoFilter.h>
+#include <qobject.h>
+#include <qstring.h>
+
+class XFIGImport : public KoFilter
+{
+ Q_OBJECT
+
+public:
+ XFIGImport( KoFilter *parent, const char *name );
+ virtual ~XFIGImport();
+
+ virtual bool filterImport( const QString &file, KoDocument *,
+ const QString &from, const QString &to,
+ const QString &config=QString::null );
+
+private:
+ void parseColorObject (istream& fin);
+ void parseArc (istream& fin, GDocument* doc);
+ void parseEllipse (istream& fin, GDocument* doc);
+ void parsePolyline (istream& fin, GDocument* doc);
+ void parseSpline (istream& fin, GDocument* doc);
+ void parseText (istream& fin, GDocument* doc);
+ void parseCompoundObject (istream& fin, GDocument* doc);
+ void buildDocument (GDocument *doc);
+
+ void setProperties (GObject* obj, int pen_color, int style, int thickness,
+ int area_fill, int fill_color);
+
+ float fig_resolution;
+ int coordinate_system;
+ int version;
+ QIntDict<QColor> colorTable;
+
+ // An object and the depth. Used for sorting objects
+ // in the object list
+ struct GObjectListItem
+ {
+ GObjectListItem() : object(0L) {} // for QValueList
+
+ GObjectListItem( int d, GObject * obj ) :
+ object(obj), depth(d) {}
+
+ GObject * object;
+ int depth;
+ bool operator < (const GObjectListItem & item ) const
+ {
+ // We want to sort by decreasing depths
+ return depth > item.depth;
+ }
+ bool operator == (const GObjectListItem & item ) const
+ {
+ return depth == item.depth;
+ }
+ };
+ QValueList<GObjectListItem> objList;
+};
+
+#endif
diff --git a/filters/karbon/xfig/xfigimport_factory.cc b/filters/karbon/xfig/xfigimport_factory.cc
new file mode 100644
index 00000000..7783072d
--- /dev/null
+++ b/filters/karbon/xfig/xfigimport_factory.cc
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2001, Rob Buis <rwlbuis@wanadoo.nl>
+ Copyright (C) 2003, Rob Buis <buis@kde.org>
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#include "xfigimport_factory.h"
+#include "xfigimport_factory.moc"
+#include "xfigimport.h"
+
+#include <kinstance.h>
+#include <kdebug.h>
+
+K_EXPORT_COMPONENT_FACTORY( libxfigimport, XFIGImportFactory )
+
+KInstance *XFIGImportFactory::s_global = 0;
+
+XFIGImportFactory::XFIGImportFactory(
+ QObject *parent,
+ const char *name) :
+ KLibFactory(parent, name)
+{
+ s_global = new KInstance("xfigimport");
+}
+
+XFIGImportFactory::~XFIGImportFactory()
+{
+ delete s_global;
+ s_global = 0L;
+}
+
+QObject *XFIGImportFactory::createObject(
+ QObject *parent,
+ const char *name,
+ const char*,
+ const QStringList &)
+{
+ if (parent && !parent->inherits("KoFilter"))
+ {
+ kdDebug(30502) << "XFIGImportFactory: parent does not inherit KoFilter" << endl;
+ return 0L;
+ }
+ XFIGImport *f = new XFIGImport((KoFilter*)parent, name);
+ return f;
+}
+
+KInstance *XFIGImportFactory::global()
+{
+ return s_global;
+}
diff --git a/filters/karbon/xfig/xfigimport_factory.h b/filters/karbon/xfig/xfigimport_factory.h
new file mode 100644
index 00000000..8da70040
--- /dev/null
+++ b/filters/karbon/xfig/xfigimport_factory.h
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2001, Rob Buis <rwlbuis@wanadoo.nl>
+ Copyright (C) 2003, Rob Buis <buis@kde.org>
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+*/
+
+#ifndef XFIGIMPORT_FACTORY_H
+#define XFIGIMPORT_FACTORY_H
+
+#include <klibloader.h>
+
+class KInstance;
+
+class XFIGImportFactory :
+ public KLibFactory
+{
+ Q_OBJECT
+public:
+ XFIGImportFactory(QObject* parent = 0, const char* name = 0);
+ virtual ~XFIGImportFactory();
+
+ virtual QObject* createObject(QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList());
+
+ static KInstance* global();
+
+private:
+ static KInstance* s_global;
+};
+#endif