Index: /applications/editors/josm/plugins/pdfimport/.classpath
===================================================================
--- /applications/editors/josm/plugins/pdfimport/.classpath	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/.classpath	(revision 23702)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/JOSM"/>
+	<classpathentry kind="lib" path="lib/PDFClown.jar"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
Index: /applications/editors/josm/plugins/pdfimport/.project
===================================================================
--- /applications/editors/josm/plugins/pdfimport/.project	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/.project	(revision 23702)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>JOSM-pdfimport</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: /applications/editors/josm/plugins/pdfimport/README
===================================================================
--- /applications/editors/josm/plugins/pdfimport/README	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/README	(revision 23702)
@@ -0,0 +1,82 @@
+README 
+======
+
+This is a plugin for extracting shapes from PDF files.
+Generally useful if you have a map in PDF file and want to automate data extraction.
+This plugin is available under the GPL licence (version 2.0 or later).
+Uses PDFClown library to parse PDF files, see http://sourceforge.net/projects/clown/ for more info.
+
+
+Layout
+======
++--- src                                source of your plugin
+  |- images                             images your plugin needs
+  |- resources                          resources your plugin needs
+
+  README                                this file
+
+  GPL-v2.0.txt                          GPL version 2 license text
+  GPL-v3.0.txt                          GPL version 3 license text
+  build.xml 				deployment build file
+  build-dev.xml 			vevelopment build file - uses local version of PDFClown
+   
+  
+Build
+=====  
+A JOSM plugin is built as a single jar. We use ant to build.
+
+See build.xml in this directory and update the plugin specific properties in the
+configuration section.
+  
+
+Maintaining versions
+====================
+There are two versions maintained with each plugin:
+   1) the main version
+      This is the lowest JOSM version required by this plugin.
+      You have to manually set the plugins main version in the build script.
+      Set the property plugin.main.version in build.xml accordingly. 
+
+   2) the build version
+      The build version is unique for every build of the plugin. It is equal
+      to the SVN revision of your plugin directory. 
+
+ Both the main version and the build version are included in properties of the plugins
+ manifest:
+    Plugin-Version      the build version
+    Plugin-Mainversion  the main version
+
+ JOSM automatically detects whether a plugin needs to be upgraded. It compares the build
+ version of the currently installed plugin jar with the build version of the plugin jar in 
+ the SVN. The main version is irrelevant for this process.  
+ 
+ Making your plugin available to JOSM users
+ ===========================================
+ When a plugin jar is checked into SVN a script updates the plugins list on the JOSM wiki:
+   http://josm.openstreetmap.de/wiki/Plugins
+ JOSM retrieves the list of available plugins and their build versions from this list.
+
+            commit      publish               read
+                       meta data              meta data 
+      Build  ==>  SVN  =======>  JOSM Wiki   <======= JOSM 
+                   ^ 
+                   ==================================
+                            fetch current plugin jar 
+ 
+ Note that you have to manually publish (commit) your plugin jar. There is no nightly build
+ in place. Everything else (pulishing meta data, updating plugins in the client) is then handled 
+ by automatic processes. 
+
+See also
+========
+* Developing Plugins 
+  http://josm.openstreetmap.de/wiki/DevelopersGuide/DevelopingPlugins
+  
+* List of JOSM Plugins
+  http://josm.openstreetmap.de/wiki/Plugins
+  
+  
+ 
+     
+
+ 
Index: /applications/editors/josm/plugins/pdfimport/build.xml
===================================================================
--- /applications/editors/josm/plugins/pdfimport/build.xml	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/build.xml	(revision 23702)
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+** This is the build file for the pdfimport plugin.
+**
+** Maintaining versions
+** ====================
+** see README.template
+**
+** Usage
+** =====
+** To build it run
+**
+**    > ant  dist
+**
+** To install the generated plugin locally (in you default plugin directory) run
+**
+**    > ant  install
+**
+** The generated plugin jar is not automatically available in JOSMs plugin configuration
+** dialog. You have to check it in first.
+**
+** Use the ant target 'publish' to check in the plugin and make it available to other
+** JOSM users:
+**    set the properties commit.message and plugin.main.version
+** and run
+**    > ant  publish
+**
+**
+-->
+<project name="pdfimport" default="dist" basedir=".">
+
+
+	<!-- enter the SVN commit message -->
+	<property name="commit.message" value="adapt to latest josm" />
+	<!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
+	<property name="plugin.main.version" value="3348" />
+
+
+	<!-- compilation properties -->
+	<property name="josm.build.dir" value="../../core" />
+	<property name="josm.home.dir" value="${user.home}/.josm" />
+	<property name="josm" location="../../core/dist/josm-custom.jar" />
+	<property name="plugin.build.dir" value="build" />
+	<property name="plugin.dist.dir" value="../../dist" />
+	<property name="plugin.name" value="${ant.project.name}" />
+	<property name="libpdfclown" value="lib/PDFClown.jar"/>	
+	<property name="plugin.jar" value="${plugin.dist.dir}/${plugin.name}.jar" />
+
+	<!-- There's no josm.jar in the svn, so point "josm" to a local copy of your JOSM binary -->
+	<property name="josm" location="../../core/dist/josm-custom.jar" />
+
+	<property name="ant.build.javac.target" value="1.5" />
+
+	<target name="init">
+		<mkdir dir="${plugin.build.dir}">
+		</mkdir>
+		<mkdir dir="${plugin.dist.dir}">
+		</mkdir>
+	</target>
+
+	<target name="compile" depends="init">
+		<echo message="creating ${plugin.jar}" />
+		<javac srcdir="src" target="1.5" destdir="build" debug="true">
+			<include name="pdfimport/**/*.java" />
+			<classpath>
+				<pathelement location="${josm}"/>
+				<pathelement location="${libpdfclown}"/>
+			</classpath>			
+		</javac>
+	</target>
+
+	<target name="revision">
+		<exec append="false" output="REVISION" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="info" />
+			<arg value="--xml" />
+			<arg value="." />
+		</exec>
+		<xmlproperty file="REVISION" prefix="version" keepRoot="false" collapseAttributes="true" />
+		<delete file="REVISION" />
+	</target>
+
+	<target name="dist" depends="compile,revision">
+ 		<unjar dest="${plugin.build.dir}" src="${libpdfclown}"/>
+		<copy todir="${plugin.build.dir}/images">
+			<fileset dir="images" />
+		</copy>
+		<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
+			<manifest>
+				<attribute name="Author" value="Viesturs" />
+				<attribute name="Plugin-Class" value="pdfimport.PdfImportPlugin" />
+				<attribute name="Plugin-Description" value="Import PDF files and convert to shapes." />
+				<attribute name="Plugin-Icon" value="images/pdf_import.png"/>
+				<attribute name="Plugin-Version" value="${version.entry.commit.revision}" />
+				<attribute name="Plugin-Date" value="${version.entry.commit.date}" />
+				<attribute name="Plugin-Link" value="http://svn.openstreetmap.org/applications/editors/josm/plugins/pdfimport/" />
+				<attribute name="Plugin-Mainversion" value="${plugin.main.version}" />
+			</manifest>
+		</jar>
+	</target>
+
+	<target name="clean">
+		<delete dir="${plugin.build.dir}" />
+		<delete file="${plugin.jar}" />
+	</target>
+
+	<target name="clean_install">
+		<delete file="${plugins}/pdfimport.jar" />
+	</target>
+
+	<target name="install" depends="dist">
+		<property environment="env" />
+		<condition property="josm.plugins.dir" value="${env.APPDATA}/JOSM/plugins" else="${user.home}/.josm/plugins">
+			<and>
+				<os family="windows" />
+			</and>
+		</condition>
+		<copy file="${plugin.jar}" todir="${josm.plugins.dir}" />
+	</target>
+
+	<!--
+	************************** Publishing the plugin *********************************** 
+	-->
+	<!--
+		** extracts the JOSM release for the JOSM version in ../core and saves it in the 
+		** property ${coreversion.info.entry.revision}
+		**
+		-->
+	<target name="core-info">
+		<exec append="false" output="core.info.xml" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="info" />
+			<arg value="--xml" />
+			<arg value="../../core" />
+		</exec>
+		<xmlproperty file="core.info.xml" prefix="coreversion" keepRoot="true" collapseAttributes="true" />
+		<echo>Building against core revision ${coreversion.info.entry.revision}.</echo>
+		<echo>Plugin-Mainversion is set to ${plugin.main.version}.</echo>
+		<delete file="core.info.xml" />
+	</target>
+
+	<!--
+		** commits the source tree for this plugin
+		-->
+	<target name="commit-current">
+		<echo>Commiting the plugin source with message '${commit.message}' ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="commit" />
+			<arg value="-m '${commit.message}'" />
+			<arg value="." />
+		</exec>
+	</target>
+
+	<!--
+		** updates (svn up) the source tree for this plugin
+		-->
+	<target name="update-current">
+		<echo>Updating plugin source ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="up" />
+			<arg value="." />
+		</exec>
+		<echo>Updating ${plugin.jar} ...</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="up" />
+			<arg value="../dist/${plugin.jar}" />
+		</exec>
+	</target>
+
+	<!--
+		** commits the plugin.jar 
+		-->
+	<target name="commit-dist">
+		<echo>
+	***** Properties of published ${plugin.jar} *****
+	Commit message    : '${commit.message}'					
+	Plugin-Mainversion: ${plugin.main.version}
+	JOSM build version: ${coreversion.info.entry.revision}
+	Plugin-Version    : ${version.entry.commit.revision}
+	***** / Properties of published ${plugin.jar} *****					
+						
+	Now commiting ${plugin.jar} ...
+	</echo>
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false">
+			<env key="LANG" value="C" />
+			<arg value="-m '${commit.message}'" />
+			<arg value="commit" />
+			<arg value="${plugin.jar}" />
+		</exec>
+	</target>
+
+	<!-- ** make sure svn is present as a command line tool ** -->
+	<target name="ensure-svn-present">
+		<exec append="true" output="svn.log" executable="svn" failifexecutionfails="false" failonerror="false" resultproperty="svn.exit.code">
+			<env key="LANG" value="C" />
+			<arg value="--version" />
+		</exec>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure svn is installed on your system.">
+			<!-- return code not set at all? Most likely svn isn't installed -->
+			<condition>
+				<not>
+					<isset property="svn.exit.code" />
+				</not>
+			</condition>
+		</fail>
+		<fail message="Fatal: command 'svn --version' failed. Please make sure a working copy of svn is installed on your system.">
+			<!-- error code from SVN? Most likely svn is not what we are looking on this system -->
+			<condition>
+				<isfailure code="${svn.exit.code}" />
+			</condition>
+		</fail>
+	</target>
+
+	<target name="publish" depends="ensure-svn-present,core-info,commit-current,update-current,clean,dist,commit-dist">
+	</target>
+
+</project>
Index: /applications/editors/josm/plugins/pdfimport/license
===================================================================
--- /applications/editors/josm/plugins/pdfimport/license	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/license	(revision 23702)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerContents.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerContents.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerContents.java	(revision 23702)
@@ -0,0 +1,16 @@
+/**
+ * 
+ */
+package pdfimport;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+public class LayerContents{
+
+	List<Point2D> points = new ArrayList<Point2D>();
+	List<PdfPath> paths = new ArrayList<PdfPath>();
+	List<PdfMultiPath> multiPaths = new ArrayList<PdfMultiPath>();
+	LayerInfo info;		
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerInfo.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerInfo.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/LayerInfo.java	(revision 23702)
@@ -0,0 +1,62 @@
+package pdfimport;
+
+import java.awt.Color;
+
+public class LayerInfo{
+	public double width;
+	public Color color;
+	public Color fillColor;
+	public boolean fill;
+	public boolean stroke;
+
+	public int nr;	
+	public int divider;
+	
+	@Override
+	public int hashCode()
+	{
+		int code =  Double.toString(width).hashCode() ^ this.divider;
+		
+		if (this.fill) {
+			code ^= this.fillColor.hashCode();
+		}
+		
+		if (this.stroke) {
+			code ^= this.color.hashCode();
+		}
+		
+		return code;
+	}
+	
+	public boolean equals(Object o)
+	{
+		LayerInfo l = (LayerInfo) o;
+		boolean eq = 
+			this.width == l.width && 
+			this.divider == l.divider && 
+			this.fill == l.fill &&
+			this.stroke == l.stroke;
+		
+		if (this.fill){
+			eq &= this.fillColor.equals(l.fillColor); 
+		}
+		
+		if (this.stroke) {			 
+			eq &= this.color.equals(l.color);			
+		}
+		
+		return eq;
+	}
+
+	public LayerInfo copy() {
+		LayerInfo result = new LayerInfo();
+		result.color = this.color;
+		result.fillColor = this.fillColor;
+		result.width = this.width;
+		result.divider = this.divider;
+		result.fill = this.fill;
+		result.stroke = this.stroke;
+		return result;
+	}
+	
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java	(revision 23702)
@@ -0,0 +1,451 @@
+package pdfimport;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import it.stefanochizzolini.clown.documents.Document;
+import it.stefanochizzolini.clown.documents.Page;
+import it.stefanochizzolini.clown.documents.contents.ContentScanner;
+import it.stefanochizzolini.clown.documents.contents.Contents;
+import it.stefanochizzolini.clown.files.File;
+import it.stefanochizzolini.clown.tokens.FileFormatException;
+
+import java.awt.BorderLayout;
+import java.awt.Cursor;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.FileNotFoundException;
+import java.util.Collection;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileFilter;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+public class LoadPdfDialog extends JFrame {
+
+	private String fileName;
+	private PDFStreamProcessor data;
+	private final OsmBuilder builder;
+	private OsmDataLayer layer;
+
+	/**
+	 * Combobox with all projections available
+	 */
+	private JComboBox projectionCombo;
+	private JTextField minXField;
+	private JTextField minYField;
+	private JTextField minEastField;
+	private JTextField minNorthField;
+	private JButton getMinButton;
+	private JButton okButton;
+	private JButton cancelButton;
+	private JButton getMaxButton;
+	private JTextField maxNorthField;
+	private JTextField maxEastField;
+	private JTextField maxYField;
+	private JTextField maxXField;
+	private JButton loadFileButton;
+	private JButton showButton;
+
+	public LoadPdfDialog() {
+
+		this.builder = new OsmBuilder();
+
+		this.buildGUI();
+		this.addListeners();
+		this.removeLayer();
+	}
+
+	private void addListeners() {
+
+		this.loadFileButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				loadFilePressed();
+			}
+		});
+
+		this.okButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				okPressed();
+			}
+		});
+
+		this.showButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				showPressed();
+			}
+		});
+
+		this.cancelButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				cancelPressed();
+			}
+		});
+
+		this.addWindowListener(new WindowAdapter()
+		{
+			@Override
+			public void windowClosing(WindowEvent e) {
+				cancelPressed();
+			}
+		});
+
+		this.getMinButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				getMinPressed();
+			}
+		});
+
+		this.getMaxButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				getMaxPressed();
+			}
+		});
+
+	}
+
+	private void buildGUI() {
+		GridBagConstraints c = new GridBagConstraints();
+		c.gridheight = 1;c.gridwidth = 1;c.weightx =1; c.weighty = 1; c.fill = GridBagConstraints.BOTH;
+
+		this.projectionCombo = new JComboBox();
+		this.projectionCombo.addItem("Select projection...");
+		for (Projection p: Projection.allProjections) {
+			this.projectionCombo.addItem(p);
+		}
+
+		this.loadFileButton = new JButton(tr("Load file..."));
+		this.okButton = new JButton(tr("Place"));
+		this.showButton = new JButton(tr("Show target"));
+		this.cancelButton = new JButton(tr("Discard"));
+
+		this.minXField = new JTextField(""+this.builder.minX);
+		this.minYField = new JTextField(""+this.builder.minY);
+		this.minEastField = new JTextField(""+this.builder.minEast);
+		this.minNorthField = new JTextField(""+this.builder.minNorth);
+		this.getMinButton = new JButton(tr("Take X and Y from selected node"));
+
+		this.maxXField = new JTextField(""+this.builder.maxX);
+		this.maxYField = new JTextField(""+this.builder.maxY);
+		this.maxEastField = new JTextField(""+this.builder.maxEast);
+		this.maxNorthField = new JTextField(""+this.builder.maxNorth);
+		this.getMaxButton = new JButton(tr("Take X and Y from selected node"));
+
+
+		JPanel selectFilePanel = new JPanel(new GridBagLayout());
+		selectFilePanel.setBorder(BorderFactory.createTitledBorder(tr("Load file")));
+		c.gridx = 0; c.gridy = 0; c.gridwidth = 1;
+		selectFilePanel.add(this.loadFileButton, c);
+
+		JPanel projectionPanel = new JPanel(new GridBagLayout());
+		projectionPanel.setBorder(BorderFactory.createTitledBorder(tr("Bind to coordinates")));
+
+		c.gridx = 0; c.gridy = 0; c.gridwidth = 1;
+		projectionPanel.add(new JLabel(tr("Projection:")), c);
+		c.gridx = 1; c.gridy = 0; c.gridwidth = 1;
+		projectionPanel.add(this.projectionCombo);
+
+		c.gridx = 0; c.gridy = 1; c.gridwidth = 2;
+		projectionPanel.add(new JLabel(tr("Bottom left (min) corner:")), c);
+		c.gridx = 0; c.gridy = 2; c.gridwidth = 1;
+		projectionPanel.add(new JLabel(tr("PDF X and Y")), c);
+		c.gridx = 1; c.gridy = 2; c.gridwidth = 1;
+		projectionPanel.add(new JLabel(tr("East and North")), c);
+		c.gridx = 0; c.gridy = 3; c.gridwidth = 1;
+		projectionPanel.add(this.minXField, c);
+		c.gridx = 0; c.gridy = 4; c.gridwidth = 1;
+		projectionPanel.add(this.minYField, c);
+		c.gridx = 1; c.gridy = 3; c.gridwidth = 1;
+		projectionPanel.add(this.minEastField, c);
+		c.gridx = 1; c.gridy = 4; c.gridwidth = 1;
+		projectionPanel.add(this.minNorthField, c);
+		c.gridx = 0; c.gridy = 5; c.gridwidth = 1;
+		projectionPanel.add(this.getMinButton, c);
+
+
+		c.gridx = 0; c.gridy = 6; c.gridwidth = 2;
+		projectionPanel.add(new JLabel(tr("Top right (max) corner:")), c);
+		c.gridx = 0; c.gridy = 7; c.gridwidth = 1;
+		projectionPanel.add(new JLabel(tr("PDF X and Y")), c);
+		c.gridx = 1; c.gridy = 7; c.gridwidth = 1;
+		projectionPanel.add(new JLabel(tr("East and North")), c);
+		c.gridx = 0; c.gridy = 8; c.gridwidth = 1;
+		projectionPanel.add(this.maxXField, c);
+		c.gridx = 0; c.gridy = 9; c.gridwidth = 1;
+		projectionPanel.add(this.maxYField, c);
+		c.gridx = 1; c.gridy = 8; c.gridwidth = 1;
+		projectionPanel.add(this.maxEastField, c);
+		c.gridx = 1; c.gridy = 9; c.gridwidth = 1;
+		projectionPanel.add(this.maxNorthField, c);
+		c.gridx = 0; c.gridy = 10; c.gridwidth = 1;
+		projectionPanel.add(this.getMaxButton, c);
+
+
+		JPanel okCancelPanel = new JPanel(new GridLayout(1,3));
+		okCancelPanel.add(this.cancelButton);
+		okCancelPanel.add(this.showButton);
+		okCancelPanel.add(this.okButton);
+
+
+		JPanel panel = new JPanel(new BorderLayout());
+		panel.add(okCancelPanel, BorderLayout.SOUTH);
+		panel.add(projectionPanel, BorderLayout.CENTER);
+		panel.add(selectFilePanel, BorderLayout.NORTH);
+
+		this.setSize(400, 400);
+		this.setContentPane(panel);
+	}
+
+
+	private void loadFilePressed() {
+		final java.io.File fileName = this.chooseFile();
+
+		if (fileName == null) {
+			return;
+		}
+
+		this.loadFileButton.setEnabled(false);
+		this.loadFileButton.setText(tr("Lading..."));
+
+
+		this.runAsBackgroundTask(
+				new Runnable() {
+					public void run() {
+						data = loadPDF(fileName.getAbsolutePath());
+					}
+				},
+				new ActionListener() {
+
+					public void actionPerformed(ActionEvent e) {
+						if (data!= null) {
+							LoadPdfDialog.this.fileName = fileName.getAbsolutePath();
+							LoadPdfDialog.this.makeLayer(tr("PDF file preview"), false);
+							LoadPdfDialog.this.loadFileButton.setText(tr("Loaded"));
+							LoadPdfDialog.this.loadFileButton.setEnabled(true);
+						}
+					}
+				});
+	}
+
+
+	private void okPressed() {
+
+		boolean ok = this.loadTransformation();
+		if (!ok){
+			return;
+		}
+
+		//rebuild layer with latest projection
+		this.makeLayer(tr("Imported PDF: ") + this.fileName, true);
+		this.setVisible(false);
+	}
+
+	private void showPressed() {
+
+		boolean ok = this.loadTransformation();
+		if (!ok){
+			return;
+		}
+
+		//zoom to new location
+		Main.map.mapView.zoomTo(builder.getWorldBounds(this.data));
+		Main.map.repaint();
+	}
+
+	private void cancelPressed() {
+		this.removeLayer();
+		this.setVisible(false);
+	}
+
+
+	private void getMinPressed() {
+		EastNorth en = this.getSelectedCoor();
+
+		if (en != null) {
+			this.minXField.setText(Double.toString(en.east()));
+			this.minYField.setText(Double.toString(en.north()));
+		}
+	}
+
+	private void getMaxPressed() {
+		EastNorth en = this.getSelectedCoor();
+
+		if (en != null) {
+			this.maxXField.setText(Double.toString(en.east()));
+			this.maxYField.setText(Double.toString(en.north()));
+		}
+	}
+
+	// Implementation methods
+
+	private EastNorth getSelectedCoor() {
+		Collection<OsmPrimitive> selected = Main.main.getCurrentDataSet().getSelected();
+
+		if (selected.size() != 1 || !(selected.iterator().next() instanceof Node)){
+			JOptionPane.showMessageDialog(Main.parent, tr("Please select exactly one node."));
+			return null;
+		}
+
+		LatLon ll = ((Node)selected.iterator().next()).getCoor();
+		return this.builder.reverseTransform(ll);
+	}
+
+
+	private java.io.File chooseFile() {
+		//get file name
+		JFileChooser fc = new JFileChooser();
+		fc.setAcceptAllFileFilterUsed(false);
+		fc.setMultiSelectionEnabled(false);
+		fc.setFileFilter(new FileFilter(){
+			@Override
+			public boolean accept(java.io.File pathname) {
+				return pathname.isDirectory() || pathname.getName().endsWith(".pdf");
+			}
+			@Override
+			public String getDescription() {
+				return tr("PDF files");
+			}
+		});
+		int result = fc.showOpenDialog(Main.parent);
+
+		if (result != JFileChooser.APPROVE_OPTION) {
+			return null;
+		}
+		else
+		{
+			return fc.getSelectedFile();
+		}
+	}
+
+	private void runAsBackgroundTask(final Runnable task, final ActionListener after) {
+		this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+		Thread t = new Thread(new Runnable()
+		{
+			public void run() {
+				task.run();
+
+				SwingUtilities.invokeLater(new Runnable(){
+					public void run() {
+						setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+						after.actionPerformed(null);
+					}
+				});
+			}
+		});
+		t.start();
+	}
+
+	private PDFStreamProcessor loadPDF(String fileName) {
+		File file;
+
+		try {
+			file = new File(fileName);
+		} catch (FileNotFoundException e1) {
+			JOptionPane
+			.showMessageDialog(
+					Main.parent,
+					tr("File not found."));
+			return null;
+		} catch (FileFormatException e1) {
+			JOptionPane
+			.showMessageDialog(
+					Main.parent,
+					tr("Could not parse file. Not a PDF file?"));
+			return null;
+		}
+
+		Document document = file.getDocument();
+		Page page = document.getPages().get(0);
+
+
+		PDFStreamProcessor processor = new PDFStreamProcessor(document);
+		processor.bounds = page.getBox();
+		Contents c = page.getContents();
+		processor.process(new ContentScanner(c));
+		processor.finish();
+		document.delete();
+
+		return processor;
+	}
+
+	private boolean loadTransformation() {
+		Object selectedProjection = this.projectionCombo.getSelectedItem();
+
+		if (!(selectedProjection instanceof Projection))
+		{
+			JOptionPane.showMessageDialog(Main.parent, tr("Please set a projection."));
+			return false;
+		}
+
+		this.builder.projection = (Projection)this.projectionCombo.getSelectedItem();
+
+		try
+		{
+			this.builder.setPdfBounds(
+					Double.parseDouble(this.minXField.getText()),
+					Double.parseDouble(this.minYField.getText()),
+					Double.parseDouble(this.maxXField.getText()),
+					Double.parseDouble(this.maxYField.getText()));
+			this.builder.setEastNorthBounds(
+					Double.parseDouble(this.minEastField.getText()),
+					Double.parseDouble(this.minNorthField.getText()),
+					Double.parseDouble(this.maxEastField.getText()),
+					Double.parseDouble(this.maxNorthField.getText()));
+		}
+		catch (Exception e) {
+			JOptionPane.showMessageDialog(Main.parent, tr("Could not parse numbers. Please check."));
+			return false;
+		}
+
+		return true;
+	}
+
+	private void makeLayer(String name, boolean isFinal) {
+		this.removeLayer();
+
+		if (builder == null) {
+			return;
+		}
+
+		DataSet data = builder.build(this.data, isFinal);
+		this.layer = new OsmDataLayer(data, name, null);
+
+		// Commit
+		this.layer.onPostLoadFromFile();
+		Main.main.addLayer(this.layer);
+		Main.map.mapView.zoomTo(builder.getWorldBounds(this.data));
+
+		this.okButton.setEnabled(true);
+		this.showButton.setEnabled(true);
+	}
+
+	private void removeLayer() {
+		if (this.layer != null) {
+			Main.main.removeLayer(this.layer);
+			this.layer = null;
+		}
+
+		this.okButton.setEnabled(false);
+		this.showButton.setEnabled(false);
+	}
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java	(revision 23702)
@@ -0,0 +1,187 @@
+package pdfimport;
+
+import java.awt.Color;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.projection.Projection;
+
+public class OsmBuilder {
+
+	public Projection projection = null;
+	public double minX = 0;
+	public double maxX = 1;
+	public double minY = 0;
+	public double maxY = 1;
+
+	public double minEast = 0;
+	public double maxEast = 10000;
+	public double minNorth = 0;
+	public double maxNorth = 10000;
+
+	public OsmBuilder()
+	{
+	}
+
+	public void setPdfBounds(double minX, double minY, double maxX, double maxY){
+		this.minX = minX;
+		this.minY = minY;
+		this.maxX = maxX;
+		this.maxY = maxY;
+	}
+
+	public void setEastNorthBounds(double minEast, double minNorth, double maxEast, double maxNorth) {
+		this.minEast = minEast;
+		this.maxEast = maxEast;
+		this.minNorth = minNorth;
+		this.maxNorth = maxNorth;
+	}
+
+
+	public Bounds getWorldBounds(PDFStreamProcessor data) {
+		LatLon min = tranformCoords(data.bounds.getMinX(), data.bounds.getMinY());
+		LatLon max = tranformCoords(data.bounds.getMaxX(), data.bounds.getMaxY());
+		return new Bounds(min, max);
+	}
+
+	public DataSet build(PDFStreamProcessor data, boolean full) {
+
+		DataSet result = new DataSet();
+
+		for (LayerContents layer: data.getResult()) {
+			this.addLayer(result, layer, full);
+		}
+		return result;
+	}
+
+
+	private void addLayer(DataSet target, LayerContents layer, boolean full) {
+		Map<Point2D, Node> point2Node = new HashMap<Point2D, Node>();
+
+		//insert nodes
+		for(Point2D pt: layer.points) {
+			Node node = new Node();
+			node.setCoor(this.tranformCoords(pt.getX(), pt.getY()));
+
+			target.addPrimitive(node);
+			point2Node.put(pt, node);
+		}
+
+		//insert ways
+		Map<PdfPath, Way> path2Way = new HashMap<PdfPath, Way>();
+
+		for (PdfPath path: layer.paths){
+			Way w = this.insertWay(path, point2Node, -1, full);
+			target.addPrimitive(w);
+			path2Way.put(path, w);
+		}
+
+		int pathId = 0;
+		for (PdfMultiPath mpath: layer.multiPaths) {
+			for (PdfPath path: mpath.paths){
+				Way w = this.insertWay(path, point2Node, pathId, full);
+				target.addPrimitive(w);
+				path2Way.put(path, w);
+			}
+			pathId ++;
+		}
+
+		if (full) {
+			//insert relations
+			for (PdfMultiPath mpath: layer.multiPaths) {
+				Relation rel = new Relation();
+
+				Map<String, String> keys = new HashMap<String, String>();
+				keys.put("type", "multipolygon");
+				keys.put("area", "yes");
+				rel.setKeys(keys);
+
+				for (PdfPath path: mpath.paths){
+					Way w = path2Way.get(path);
+					rel.addMember(new RelationMember("", w));
+				}
+
+				target.addPrimitive(rel);
+			}
+		}
+	}
+
+	private Way insertWay(PdfPath path, Map<Point2D, Node> point2Node, int multipathId, boolean full) {
+
+		List<Node> nodes = new ArrayList<Node>(path.points.size());
+
+		for (Point2D point: path.points) {
+			Node node = point2Node.get(point);
+			if (node == null) {
+				throw new RuntimeException();
+			}
+
+			nodes.add(node);
+		}
+
+		Map<String, String> keys = new HashMap<String, String>();
+
+		if (full) {
+			keys.put("PDF_nr", "" + path.nr);
+			keys.put("PDF_layer", "" + path.layer.info.nr);
+			keys.put("PDF_closed", "" + path.isClosed());
+
+			if (path.layer.info.fill){
+				keys.put("PDF_fillColor", printColor(path.layer.info.fillColor));
+			}
+
+			if (path.layer.info.stroke) {
+				keys.put("PDF_lineColor", printColor(path.layer.info.color));
+			}
+
+			if (multipathId != -1){
+				keys.put("PDF_multipath", ""+ multipathId);
+			}
+			else if (path.layer.info.fill) {
+				keys.put("area", "yes");
+			}
+		}
+
+		Way newWay = new Way();
+		newWay.setNodes(nodes);
+		newWay.setKeys(keys);
+		return newWay;
+	}
+
+	private String printColor(Color col){
+		return "#" + Integer.toHexString(col.getRGB() & 0xffffff);
+	}
+
+
+	private LatLon tranformCoords(double x, double y) {
+
+		if (this.projection == null){
+			return new LatLon(y/1000, x/1000);
+		}
+		else{
+			x = (x - this.minX) * (this.maxEast - this.minEast) / (this.maxX - this.minX)  + this.minEast;
+			y = (y - this.minY) * (this.maxNorth - this.minNorth) /  (this.maxY - this.minY) + this.minNorth;
+			return this.projection.eastNorth2latlon(new EastNorth(x, y));
+		}
+	}
+
+	public EastNorth reverseTransform(LatLon coor) {
+		if (this.projection == null){
+			return new EastNorth(coor.lon() * 1000, coor.lat() * 1000);
+		}
+		else{
+			return null;
+		}
+	}
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java	(revision 23702)
@@ -0,0 +1,324 @@
+package pdfimport;
+
+import it.stefanochizzolini.clown.documents.Document;
+import it.stefanochizzolini.clown.documents.contents.ContentScanner;
+import it.stefanochizzolini.clown.documents.contents.Contents;
+import it.stefanochizzolini.clown.documents.contents.ContentScanner.GraphicsState;
+import it.stefanochizzolini.clown.documents.contents.colorSpaces.ColorSpace;
+import it.stefanochizzolini.clown.documents.contents.colorSpaces.DeviceGrayColorSpace;
+import it.stefanochizzolini.clown.documents.contents.colorSpaces.DeviceRGBColorSpace;
+import it.stefanochizzolini.clown.documents.contents.objects.BeginSubpath;
+import it.stefanochizzolini.clown.documents.contents.objects.CloseSubpath;
+import it.stefanochizzolini.clown.documents.contents.objects.ContainerObject;
+import it.stefanochizzolini.clown.documents.contents.objects.ContentObject;
+import it.stefanochizzolini.clown.documents.contents.objects.DrawCurve;
+import it.stefanochizzolini.clown.documents.contents.objects.DrawLine;
+import it.stefanochizzolini.clown.documents.contents.objects.DrawRectangle;
+import it.stefanochizzolini.clown.documents.contents.objects.EndPathNoOp;
+import it.stefanochizzolini.clown.documents.contents.objects.FillEvenOdd;
+import it.stefanochizzolini.clown.documents.contents.objects.FillStrokeEvenOdd;
+import it.stefanochizzolini.clown.documents.contents.objects.GenericOperation;
+import it.stefanochizzolini.clown.documents.contents.objects.LocalGraphicsState;
+import it.stefanochizzolini.clown.documents.contents.objects.ModifyCTM;
+import it.stefanochizzolini.clown.documents.contents.objects.Path;
+import it.stefanochizzolini.clown.documents.contents.objects.SetLineCap;
+import it.stefanochizzolini.clown.documents.contents.objects.SetLineWidth;
+import it.stefanochizzolini.clown.documents.contents.objects.Stroke;
+import it.stefanochizzolini.clown.documents.contents.objects.Text;
+import it.stefanochizzolini.clown.objects.PdfDirectObject;
+import it.stefanochizzolini.clown.objects.PdfInteger;
+import it.stefanochizzolini.clown.objects.PdfReal;
+
+import java.awt.Color;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.RuntimeErrorException;
+
+public class PDFStreamProcessor {
+
+	private LayerInfo info;
+	public Rectangle2D bounds;
+	int pathNo = 0;
+
+	PathOptimizer optimizer = new PathOptimizer();
+	Map<LayerInfo, LayerInfo> multipathLayers = new HashMap<LayerInfo, LayerInfo>();
+	private GraphicsState state;
+	private DeviceRGBColorSpace rgbSpace;
+	private DeviceGrayColorSpace graySpace;
+
+	public PDFStreamProcessor(Document doc) {
+		
+		this.rgbSpace = new DeviceRGBColorSpace(doc);
+		this.graySpace = new DeviceGrayColorSpace(doc);
+		
+		this.info = new LayerInfo();
+	}
+	
+	public void finish() {
+		this.rgbSpace = null;
+		this.graySpace = null;
+		this.state = null;		
+		this.optimizer.optimize();
+	}
+	
+	public List<LayerContents> getResult() {
+		return this.optimizer.getLayers();
+	}
+
+	public void process(ContentScanner level) {
+		if(level == null)
+			return;
+
+	    while(level.moveNext()) {		
+			ContentObject object = level.getCurrent();			
+			if(object instanceof ContainerObject) {
+				// Scan the inner level!
+				process(level.getChildLevel());
+			} 
+			else {
+				addObject(level);
+			}
+	    }
+	}	
+	
+	public void addObject(ContentScanner level){
+		
+		ContentObject obj = level.getCurrent();
+		
+		if (obj instanceof Path)
+		{
+			this.state = level.getChildLevel().getState();
+			this.parsePath((Path)obj);
+		}
+		else if (obj instanceof Text){
+			//maybe something here
+		}			
+		else if (obj instanceof EndPathNoOp){
+			//nothing here
+			this.info.divider ++;
+		}	
+		else if (obj instanceof GenericOperation) {
+			this.state = level.getState();
+			//operations PDF clown cannot handle
+			parseGO((GenericOperation) obj, false);
+		}
+		else {
+			int a = 10;
+			a++;	
+		}
+	}
+
+	private void parseGO(GenericOperation go, boolean setDivider) {
+		String op = go.getOperator();
+		boolean parsed = true;
+		
+		if (op.equals("RG")) {
+			this.state.strokeColorSpace = this.rgbSpace;
+			this.state.strokeColor = this.rgbSpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
+		}
+		else if (op.equals("G")) {
+			this.state.strokeColorSpace = this.graySpace;
+			this.state.strokeColor = this.graySpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
+		}
+		else if (op.equals("rg")) {
+			this.state.fillColorSpace = this.rgbSpace;
+			this.state.fillColor = this.rgbSpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
+		}
+		else if (op.equals("g")) {
+			this.state.fillColorSpace = this.graySpace;
+			this.state.fillColor = this.graySpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
+		}
+		else {
+			parsed = false;
+			//nothing here
+			int a = 10;
+			a++;	
+			a++;
+		}
+		
+		if (parsed && setDivider) {
+			this.info.divider ++;
+		}
+	}
+
+	private void parsePath(Path path) {
+		
+		List<PdfPath> paths = this.getPathNodes(path);
+		this.updateInfoFromState();
+		
+		for (PdfPath p: paths){
+			p.nr = pathNo;
+		}
+		
+		pathNo ++;		
+		
+		if (paths.size() > 1) {			
+			this.optimizer.addMultiPath(this.info, paths);
+		}
+		else if (paths.size() == 1) {
+			this.optimizer.addPath(this.info, paths.get(0));
+		}
+	}
+	
+	private List<PdfPath> getPathNodes(Path path) {
+		List<PdfPath> result = new ArrayList<PdfPath>(2); 
+		List<Point2D> points = new ArrayList<Point2D>(2);
+		this.info.fill = false;
+		this.info.stroke = true;
+	
+		for (ContentObject obj:path.getObjects()) {
+			Point2D point = null;
+			
+			if (obj instanceof BeginSubpath) {
+				if (points.size() >= 2) {
+					result.add(new PdfPath(points));
+					points = new ArrayList<Point2D>(2);
+				}
+				
+				BeginSubpath b = (BeginSubpath)obj;
+				point = b.getPoint();
+			} else if (obj instanceof DrawLine) {
+				DrawLine l = (DrawLine)obj;
+				point = l.getPoint();
+			}
+			else if (obj instanceof DrawCurve) {
+				
+				DrawCurve c = (DrawCurve) obj;				
+				point = c.getPoint();			
+			}
+			else if (obj instanceof Stroke) {
+				//draw line mode..
+			}
+			else if (obj instanceof EndPathNoOp) {
+				if (points.size() >= 2) {
+					result.add(new PdfPath(points));
+					points = new ArrayList<Point2D>(2);
+				}
+			}
+			else if (obj instanceof CloseSubpath) {
+				if (points.size() >= 2) {
+					result.add(new PdfPath(points));
+					points = new ArrayList<Point2D>(2);
+				}
+			}
+			else if (obj instanceof FillEvenOdd) {
+				this.info.fill = true;
+				this.info.stroke = false;
+			}
+			else if (obj instanceof FillStrokeEvenOdd){
+				this.info.fill = true;
+				this.info.stroke = true;
+			}
+			else if (obj instanceof GenericOperation) {
+				this.parseGO((GenericOperation)obj, false);
+			}
+			else if (obj instanceof DrawRectangle) {
+				if (points.size() >= 2)
+				{
+					result.add(new PdfPath(points));
+					points = new ArrayList<Point2D>(2);
+				}				
+					
+				DrawRectangle r = (DrawRectangle) obj;
+				
+				points.add(this.parsePoint(new Point2D.Double(r.getX(), r.getY())));
+				points.add(this.parsePoint(new Point2D.Double(r.getX()+r.getWidth(), r.getY())));
+				points.add(this.parsePoint(new Point2D.Double(r.getX()+r.getWidth(), r.getY()+r.getHeight())));
+				points.add(this.parsePoint(new Point2D.Double(r.getX(), r.getY()+r.getHeight())));
+				points.add(points.get(0));
+				result.add(new PdfPath(points));				
+				points = new ArrayList<Point2D>(2);
+			}
+			else {				
+				int a = 10;
+				a++;
+			}
+			
+			//add point
+			if (point != null)
+			{	
+				boolean sameAsPrevPoint = (points.size() > 0) &&points.get(points.size() - 1).equals(point);				
+				if (!sameAsPrevPoint) {
+					points.add(this.parsePoint(point));
+				}
+			}		
+		}			
+		
+		if (points.size() >= 2)
+		{
+			result.add(new PdfPath(points));	
+		}
+	
+		return result;
+	}	
+
+	private Point2D parsePoint(Point2D point) {
+		point = this.state.userToDeviceSpace(point);
+		return this.optimizer.getUniquePoint(point);
+	}
+
+
+	
+	private void updateInfoFromState() {
+		this.info.color = getColor(this.state.strokeColor);
+		this.info.fillColor = getColor(this.state.fillColor);
+		this.info.width = this.state.lineWidth;		
+	}
+		
+	private Color getColor(
+			it.stefanochizzolini.clown.documents.contents.colorSpaces.Color col) {
+		ColorSpace space = col.getColorSpace();
+		
+		if (space instanceof DeviceRGBColorSpace) {
+			return new Color(
+					(float)col.getComponents()[0],
+					(float)col.getComponents()[1],
+					(float)col.getComponents()[2]);
+		}
+		else if (space instanceof DeviceGrayColorSpace) {
+			return new Color(
+					(float)col.getComponents()[0],
+					(float)col.getComponents()[0],
+					(float)col.getComponents()[0]);
+		}
+		else {
+			throw new RuntimeException("Unexpected colour space: "+space.toString());
+		}		
+	}
+
+	private Color addColor(GenericOperation go) {
+		List<PdfDirectObject> operands = go.getOperands();		
+		PdfDirectObject o1 = operands.get(0);
+		PdfDirectObject o2 = operands.get(1);
+		PdfDirectObject o3 = operands.get(2);
+		Color c =new Color(parseFloat(o1), parseFloat(o2), parseFloat(o3));
+		return c;
+	}
+	
+	
+	private Color addGrayColor(GenericOperation go) {
+		List<PdfDirectObject> operands = go.getOperands();		
+		PdfDirectObject o1 = operands.get(0);
+		Color c =new Color(parseFloat(o1), parseFloat(o1), parseFloat(o1));
+		return c;
+	}
+		
+	
+	private float parseFloat(PdfDirectObject obj) {
+		if (obj instanceof PdfReal) {
+			return (float)((PdfReal)obj).getNumberValue();
+		}
+		else if (obj instanceof PdfInteger) {
+			return (float)((PdfInteger)obj).getNumberValue();
+		}
+		else {
+			return 0.0f;
+		}
+	}	
+
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java	(revision 23702)
@@ -0,0 +1,293 @@
+package pdfimport;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class PathOptimizer {
+	
+	public Map<Point2D, Point2D> uniquePointMap;
+	private Map<LayerInfo, LayerContents> layerMap;
+	private List<LayerContents> layers;
+	
+	public PathOptimizer()
+	{
+		uniquePointMap = new HashMap<Point2D, Point2D>();
+		layerMap = new HashMap<LayerInfo, LayerContents>();
+		layers = new ArrayList<LayerContents>();
+	}
+
+	public Point2D getUniquePoint(Point2D point) {
+
+		if (this.uniquePointMap.containsKey(point)){
+			return this.uniquePointMap.get(point);
+		}
+		else {
+			this.uniquePointMap.put(point, point);
+			return point;
+		}		
+	}
+	
+	public void addPath(LayerInfo info, PdfPath path)
+	{
+		LayerContents layer = this.getLayer(info);
+		layer.paths.add(path);
+	}
+		
+	public void addMultiPath(LayerInfo info, List<PdfPath> paths) {
+		LayerContents layer = this.getLayer(info);
+		PdfMultiPath p = new PdfMultiPath(paths);
+		layer.multiPaths.add(p);					
+	}	
+	
+	private LayerContents getLayer(LayerInfo info) {
+		LayerContents layer;
+		
+		if (this.layerMap.containsKey(info))
+		{
+			layer = this.layerMap.get(info);
+		}
+		else
+		{
+			layer = new LayerContents();
+			layer.info = info.copy();
+			layer.info.nr = this.layers.size();
+			this.layerMap.put(layer.info, layer);
+			this.layers.add(layer);
+		}
+
+		return layer;
+	}
+	
+	public void optimize()
+	{
+		for(LayerContents layer: this.layers) {
+			this.optimizeLayer(layer);			
+		}
+		
+		List<LayerContents> newLayers = new ArrayList<LayerContents>();
+		int nr = 0;
+		
+		for(LayerContents l: this.layers) {
+			List<LayerContents> splitResult = splitBySegmentKind(l);
+			
+			for(LayerContents ll: splitResult) {
+				ll.info.nr = nr;
+				nr ++;
+				newLayers.add(ll);
+			}
+		}
+		
+		this.layers = newLayers;
+		
+		for(LayerContents layer: this.layers) {
+			finalizeLayer(layer);
+		}
+	}
+
+	private void finalizeLayer(LayerContents layer){
+		Set<Point2D> points = new HashSet<Point2D>();
+		layer.points = new ArrayList<Point2D>();
+		
+		for(PdfPath pp: layer.paths){
+			pp.layer = layer;
+			
+			for(Point2D point: pp.points){
+				if (!points.contains(point)) {
+					layer.points.add(point);
+					points.add(point);
+				}
+			}	
+		}
+		
+		for (PdfMultiPath multipath: layer.multiPaths) {
+			multipath.layer = layer;
+			for(PdfPath pp: multipath.paths){
+				pp.layer = layer;
+				
+				for(Point2D point: pp.points){
+					if (!points.contains(point)) {
+						layer.points.add(point);
+						points.add(point);
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * This method merges together paths with common end nodes. 
+	 * @param layer the layer to process.
+	 */
+	private void optimizeLayer(LayerContents layer) {
+		Map<Point2D, PdfPath> pathEndpoints = new HashMap<Point2D, PdfPath>();
+		Set<PdfPath> mergedPaths = new HashSet<PdfPath>();		
+	
+		/*
+		//sort paths, longest first
+		List<PdfPath> sortedPaths = new ArrayList<PdfPath>();
+		
+		for(PdfPath path: layer.paths) {
+			path.calculateLength();
+			sortedPaths.add(path);
+		}
+		
+		Collections.sort(sortedPaths, new Comparator<PdfPath>(){
+			public int compare(PdfPath o1, PdfPath o2) {
+
+				if (o1.length > o2.length) {
+					return -1;
+				} else if (o1.length < o2.length) {
+					return 1;
+				} else {
+					return 0;
+				}
+			}
+			
+		});
+		*/
+	
+		for(PdfPath pp: layer.paths){
+						
+			PdfPath path = pp;
+			boolean changed = true;
+			
+			while (changed && !path.isClosed()) {
+				changed  = false;
+				
+				if (pathEndpoints.containsKey(path.firstPoint())){					
+					PdfPath p1 = pathEndpoints.get(path.firstPoint());
+					pathEndpoints.remove(p1.firstPoint());
+					pathEndpoints.remove(p1.lastPoint());
+									
+					List<Point2D> newNodes = tryMergeNodeLists(path.points, p1.points);
+					path.points = newNodes;									
+					mergedPaths.add(p1);
+					changed = true;
+				}
+				
+				if (pathEndpoints.containsKey(path.lastPoint())){					
+					PdfPath p1 = pathEndpoints.get(path.lastPoint());
+					pathEndpoints.remove(p1.firstPoint());
+					pathEndpoints.remove(p1.lastPoint());
+									
+					List<Point2D> newNodes = tryMergeNodeLists(path.points, p1.points);
+					path.points = newNodes;									
+					mergedPaths.add(p1);
+					changed = true;
+				}				
+			}	
+			
+			if (!path.isClosed()){
+				pathEndpoints.put(path.firstPoint(), path);
+				pathEndpoints.put(path.lastPoint(), path);
+			}
+		}
+		
+		List<PdfPath> resultPaths = new ArrayList<PdfPath>();
+		
+		for(PdfPath path: layer.paths) {
+			if (!mergedPaths.contains(path)){
+				resultPaths.add(path);
+			}
+		}
+				
+		layer.paths = resultPaths;
+	}
+	
+	private List<LayerContents> splitBySegmentKind(LayerContents layer)
+	{
+		List<PdfPath> singleSegmentPaths = new ArrayList<PdfPath>();
+		List<PdfPath> multiSegmentPaths = new ArrayList<PdfPath>();
+		List<PdfPath> closedPaths = new ArrayList<PdfPath>();
+		
+		for(PdfPath path: layer.paths) {
+			if (path.points.size() <= 3) {
+				singleSegmentPaths.add(path);
+			}
+			else if (path.isClosed()) {
+				closedPaths.add(path);
+			}
+			else {
+				multiSegmentPaths.add(path);
+			}
+		}
+		
+		List<LayerContents> layers = new ArrayList<LayerContents>();
+		
+		if (multiSegmentPaths.size() > 0) {
+			LayerContents l = new LayerContents();
+			l.paths = multiSegmentPaths;
+			l.info = layer.info.copy();
+			
+			layers.add(l);
+		}
+		
+		if (singleSegmentPaths.size() > 0) {
+			LayerContents l = new LayerContents();
+			l.paths = singleSegmentPaths;
+			l.info = layer.info.copy();
+			layers.add(l);
+		}
+
+		if (closedPaths.size() > 0 || layer.multiPaths.size() > 0) {
+			LayerContents l = new LayerContents();
+			l.paths = closedPaths;
+			l.info = layer.info.copy();
+			l.multiPaths = layer.multiPaths;
+			layers.add(l);
+		}
+		
+		return layers;
+	}
+	
+	
+
+	private List<Point2D> tryMergeNodeLists(List<Point2D> nodes1, List<Point2D> nodes2) {
+		
+		boolean nodes1Closed = (nodes1.get(0) == nodes1.get(nodes1.size() - 1));
+		boolean nodes2Closed = (nodes2.get(0) == nodes2.get(nodes2.size() - 1));
+		
+		if (nodes1Closed || nodes2Closed) {
+			return null;
+		}
+		
+		if (nodes1.get(nodes1.size() - 1) == nodes2.get(0)) {
+			nodes1.remove(nodes1.size() -1);
+			nodes1.addAll(nodes2);
+			return nodes1;
+		}
+		else if (nodes1.get(nodes1.size() - 1) == nodes2.get(nodes2.size() -1)) {
+			nodes1.remove(nodes1.size() -1);
+			for (int pos = nodes2.size() - 1; pos >= 0; pos --) {
+				nodes1.add(nodes2.get(pos));
+			}
+			
+			return nodes1;
+		} 
+		else if (nodes1.get(0) == nodes2.get(nodes2.size() - 1)) {
+			nodes1.remove(0);
+			nodes1.addAll(0, nodes2);
+			return nodes1;
+		} 
+		else if (nodes1.get(0) == nodes2.get(0)) {
+			nodes1.remove(0);			
+			for (int pos = 0; pos < nodes2.size(); pos ++) {
+				nodes1.add(0, nodes2.get(pos));
+			}
+			
+			return nodes1;
+		} else {
+			return null;
+		}
+	}
+
+	public List<LayerContents> getLayers() {
+		return this.layers;
+	}
+
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportAction.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportAction.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportAction.java	(revision 23702)
@@ -0,0 +1,59 @@
+// License: GPL.
+package pdfimport;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import it.stefanochizzolini.clown.documents.Document;
+import it.stefanochizzolini.clown.documents.Page;
+import it.stefanochizzolini.clown.documents.contents.objects.ContentObject;
+import it.stefanochizzolini.clown.files.File;
+import it.stefanochizzolini.clown.tokens.FileFormatException;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import java.io.FileNotFoundException;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileFilter;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Loads a PDF file into a new layer.
+ *
+ */
+public class PdfImportAction extends JosmAction {
+
+    public PdfImportAction() {
+        super(tr("Import PDF file"), "pdf_import",
+                tr("Import PDF file."), Shortcut.registerShortcut(
+                        "tools:pdfimport", tr("Tool: {0}",
+                                tr("Import PDF file")), KeyEvent.VK_P,
+                        Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
+    }
+
+    /**
+     * The action button has been clicked
+     *
+     * @param e
+     *            Action Event
+     */
+    public void actionPerformed(ActionEvent e) {
+    	
+        //show dialog asking to select coordinate axes and input coordinates and projection.
+        LoadPdfDialog dialog = new LoadPdfDialog();
+        dialog.setAlwaysOnTop(true);
+        dialog.setTitle(tr("Import PDF"));
+        dialog.setVisible(true);
+    }
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportPlugin.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportPlugin.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfImportPlugin.java	(revision 23702)
@@ -0,0 +1,40 @@
+package pdfimport;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
+
+/**
+ * A plugin to import a PDF file.
+ */
+public class PdfImportPlugin extends Plugin {
+
+    protected String name;
+
+    public PdfImportPlugin(PluginInformation info) {
+        super(info);
+        name = tr("Import PDf file");
+        JMenu toolsMenu = null;
+        for (int i = 0; i < Main.main.menu.getMenuCount() && toolsMenu == null; i++) {
+            JMenu menu = Main.main.menu.getMenu(i);
+            String name = menu.getText();
+            if (name != null && name.equals(tr("Tools"))) {
+                toolsMenu = menu;
+            }
+        }
+
+        if (toolsMenu == null) {
+            toolsMenu = new JMenu(name);
+            toolsMenu.add(new JMenuItem(new PdfImportAction()));
+            Main.main.menu.add(toolsMenu, 2);
+        } else {
+            toolsMenu.addSeparator();
+            toolsMenu.add(new JMenuItem(new PdfImportAction()));
+        }
+    }
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfMultiPath.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfMultiPath.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfMultiPath.java	(revision 23702)
@@ -0,0 +1,14 @@
+package pdfimport;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PdfMultiPath {
+	public List<PdfPath> paths;
+	public LayerContents layer;
+
+	public PdfMultiPath(List<PdfPath> paths2) {
+		paths = paths2;
+	}
+		
+}
Index: /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfPath.java
===================================================================
--- /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfPath.java	(revision 23702)
+++ /applications/editors/josm/plugins/pdfimport/src/pdfimport/PdfPath.java	(revision 23702)
@@ -0,0 +1,39 @@
+package pdfimport;
+
+import java.awt.geom.Point2D;
+import java.util.List;
+
+public class PdfPath {
+	public List<Point2D> points;
+	public double length;
+	
+	LayerContents layer;
+	public int nr;
+	
+	
+	public PdfPath(List<Point2D> nodes) {
+		points = nodes;		
+	}
+
+	public boolean isClosed() {		
+		return points.size() > 1 && points.get(0) == points.get(points.size() - 1); 
+	}
+
+	public Point2D firstPoint() {
+		return points.get(0);	
+	}
+
+	public Point2D lastPoint() {
+		return points.get(points.size() - 1);	
+	}
+	
+	public void calculateLength() {
+		double len = 0;
+		
+		for(int pos =1; pos < points.size(); pos ++) {
+			len += points.get(pos).distance(points.get(pos -1));
+		}
+		
+		this.length = len;
+	}
+}
