Index: applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java
===================================================================
--- applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java	(revision 23737)
+++ applications/editors/josm/plugins/pdfimport/src/pdfimport/LoadPdfDialog.java	(revision 23746)
@@ -19,4 +19,5 @@
 import java.awt.event.WindowEvent;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.Collection;
 
@@ -41,4 +42,5 @@
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.io.OsmExporter;
 
 public class LoadPdfDialog extends JFrame {
@@ -67,4 +69,5 @@
 	private JButton loadFileButton;
 	private JButton showButton;
+	private JButton saveButton;
 
 	public LoadPdfDialog() {
@@ -88,4 +91,10 @@
 			public void actionPerformed(ActionEvent e) {
 				okPressed();
+			}
+		});
+
+		this.saveButton.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				savePressed();
 			}
 		});
@@ -137,4 +146,5 @@
 		this.loadFileButton = new JButton(tr("Load file..."));
 		this.okButton = new JButton(tr("Place"));
+		this.saveButton = new JButton(tr("Save"));
 		this.showButton = new JButton(tr("Show target"));
 		this.cancelButton = new JButton(tr("Discard"));
@@ -206,5 +216,5 @@
 		okCancelPanel.add(this.showButton);
 		okCancelPanel.add(this.okButton);
-
+		okCancelPanel.add(this.saveButton);
 
 		JPanel panel = new JPanel(new BorderLayout());
@@ -261,4 +271,23 @@
 	}
 
+	private void savePressed() {
+		boolean ok = this.loadTransformation();
+		if (!ok){
+			return;
+		}
+
+		java.io.File file = this.chooseSaveFile();
+
+		if (file == null){
+			return;
+		}
+
+		//rebuild layer with latest projection
+		this.removeLayer();
+		this.saveLayer(file);
+		this.setVisible(false);
+	}
+
+
 	private void showPressed() {
 
@@ -325,4 +354,30 @@
 			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 java.io.File chooseSaveFile() {
+		//get file name
+		JFileChooser fc = new JFileChooser();
+		fc.setAcceptAllFileFilterUsed(true);
+		fc.setMultiSelectionEnabled(false);
+		fc.setFileFilter(new FileFilter(){
+			@Override
+			public boolean accept(java.io.File pathname) {
+				return pathname.isDirectory() || pathname.getName().endsWith(".osm");
+			}
+			@Override
+			public String getDescription() {
+				return tr("OSM files");
 			}
 		});
@@ -449,3 +504,18 @@
 		this.showButton.setEnabled(false);
 	}
+
+	private void saveLayer(java.io.File file) {
+		DataSet data = builder.build(this.data, true);
+		OsmDataLayer layer = new OsmDataLayer(data, file.getName(), file);
+
+		OsmExporter exporter = new OsmExporter();
+
+		try {
+			exporter.exportData(file, layer);
+		}
+		catch(IOException e){
+			//TODO:
+		}
+	}
+
 }
Index: applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java
===================================================================
--- applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java	(revision 23737)
+++ applications/editors/josm/plugins/pdfimport/src/pdfimport/OsmBuilder.java	(revision 23746)
@@ -83,5 +83,5 @@
 
 		for (PdfPath path: layer.paths){
-			Way w = this.insertWay(path, point2Node, -1, full);
+			Way w = this.insertWay(path, point2Node, -1, full, false);
 			target.addPrimitive(w);
 			path2Way.put(path, w);
@@ -91,5 +91,5 @@
 		for (PdfMultiPath mpath: layer.multiPaths) {
 			for (PdfPath path: mpath.paths){
-				Way w = this.insertWay(path, point2Node, pathId, full);
+				Way w = this.insertWay(path, point2Node, pathId, full, true);
 				target.addPrimitive(w);
 				path2Way.put(path, w);
@@ -118,5 +118,5 @@
 	}
 
-	private Way insertWay(PdfPath path, Map<Point2D, Node> point2Node, int multipathId, boolean full) {
+	private Way insertWay(PdfPath path, Map<Point2D, Node> point2Node, int multipathId, boolean full, boolean multipolygon) {
 
 		List<Node> nodes = new ArrayList<Node>(path.points.size());
@@ -149,5 +149,5 @@
 				keys.put("PDF_multipath", ""+ multipathId);
 			}
-			else if (path.layer.info.fill) {
+			else if (path.layer.info.fill && !multipolygon) {
 				keys.put("area", "yes");
 			}
Index: applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java
===================================================================
--- applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java	(revision 23737)
+++ applications/editors/josm/plugins/pdfimport/src/pdfimport/PDFStreamProcessor.java	(revision 23746)
@@ -3,5 +3,4 @@
 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;
@@ -19,9 +18,5 @@
 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;
@@ -38,9 +33,7 @@
 import java.util.Map;
 
-import javax.management.RuntimeErrorException;
-
 public class PDFStreamProcessor {
 
-	private LayerInfo info;
+	private final LayerInfo info;
 	public Rectangle2D bounds;
 	int pathNo = 0;
@@ -53,18 +46,18 @@
 
 	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.state = null;
 		this.optimizer.optimize();
 	}
-	
+
 	public List<LayerContents> getResult() {
 		return this.optimizer.getLayers();
@@ -75,20 +68,20 @@
 			return;
 
-	    while(level.moveNext()) {		
-			ContentObject object = level.getCurrent();			
+		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)
 		{
@@ -98,9 +91,9 @@
 		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();
@@ -110,5 +103,5 @@
 		else {
 			int a = 10;
-			a++;	
+			a++;
 		}
 	}
@@ -117,6 +110,7 @@
 		String op = go.getOperator();
 		boolean parsed = true;
-		
-		if (op.equals("RG")) {
+		//FIXME - currently mapping ICC colors (SCN) to device RGB.
+
+		if (op.equals("RG") || op.equals("SCN")) {
 			this.state.strokeColorSpace = this.rgbSpace;
 			this.state.strokeColor = this.rgbSpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
@@ -126,5 +120,5 @@
 			this.state.strokeColor = this.graySpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
 		}
-		else if (op.equals("rg")) {
+		else if (op.equals("rg") || op.equals("scn")) {
 			this.state.fillColorSpace = this.rgbSpace;
 			this.state.fillColor = this.rgbSpace.getColor(go.getOperands().toArray(new PdfDirectObject[3]));
@@ -138,8 +132,8 @@
 			//nothing here
 			int a = 10;
-			a++;	
 			a++;
-		}
-		
+			a++;
+		}
+
 		if (parsed && setDivider) {
 			this.info.divider ++;
@@ -148,15 +142,15 @@
 
 	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) {			
+
+		pathNo ++;
+
+		if (paths.size() > 1) {
 			this.optimizer.addMultiPath(this.info, paths);
 		}
@@ -165,14 +159,14 @@
 		}
 	}
-	
+
 	private List<PdfPath> getPathNodes(Path path) {
-		List<PdfPath> result = new ArrayList<PdfPath>(2); 
+		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) {
@@ -180,5 +174,5 @@
 					points = new ArrayList<Point2D>(2);
 				}
-				
+
 				BeginSubpath b = (BeginSubpath)obj;
 				point = b.getPoint();
@@ -188,7 +182,7 @@
 			}
 			else if (obj instanceof DrawCurve) {
-				
-				DrawCurve c = (DrawCurve) obj;				
-				point = c.getPoint();			
+
+				DrawCurve c = (DrawCurve) obj;
+				point = c.getPoint();
 			}
 			else if (obj instanceof Stroke) {
@@ -223,8 +217,8 @@
 					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())));
@@ -232,29 +226,29 @@
 				points.add(this.parsePoint(new Point2D.Double(r.getX(), r.getY()+r.getHeight())));
 				points.add(points.get(0));
-				result.add(new PdfPath(points));				
+				result.add(new PdfPath(points));
 				points = new ArrayList<Point2D>(2);
 			}
-			else {				
+			else {
 				int a = 10;
 				a++;
 			}
-			
+
 			//add point
 			if (point != null)
-			{	
-				boolean sameAsPrevPoint = (points.size() > 0) &&points.get(points.size() - 1).equals(point);				
+			{
+				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));	
-		}
-	
+			result.add(new PdfPath(points));
+		}
+
 		return result;
-	}	
+	}
 
 	private Point2D parsePoint(Point2D point) {
@@ -264,15 +258,19 @@
 
 
-	
+
 	private void updateInfoFromState() {
 		this.info.color = getColor(this.state.strokeColor);
 		this.info.fillColor = getColor(this.state.fillColor);
-		this.info.width = this.state.lineWidth;		
-	}
-		
+		this.info.width = this.state.lineWidth;
+	}
+
 	private Color getColor(
 			it.stefanochizzolini.clown.documents.contents.colorSpaces.Color col) {
+		if (col == null) {
+			return Color.BLACK;
+		}
+
 		ColorSpace space = col.getColorSpace();
-		
+
 		if (space instanceof DeviceRGBColorSpace) {
 			return new Color(
@@ -289,9 +287,9 @@
 		else {
 			throw new RuntimeException("Unexpected colour space: "+space.toString());
-		}		
+		}
 	}
 
 	private Color addColor(GenericOperation go) {
-		List<PdfDirectObject> operands = go.getOperands();		
+		List<PdfDirectObject> operands = go.getOperands();
 		PdfDirectObject o1 = operands.get(0);
 		PdfDirectObject o2 = operands.get(1);
@@ -300,14 +298,14 @@
 		return c;
 	}
-	
-	
+
+
 	private Color addGrayColor(GenericOperation go) {
-		List<PdfDirectObject> operands = go.getOperands();		
+		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) {
@@ -320,5 +318,5 @@
 			return 0.0f;
 		}
-	}	
+	}
 
 }
Index: applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java
===================================================================
--- applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java	(revision 23737)
+++ applications/editors/josm/plugins/pdfimport/src/pdfimport/PathOptimizer.java	(revision 23746)
@@ -10,9 +10,9 @@
 
 public class PathOptimizer {
-	
+
 	public Map<Point2D, Point2D> uniquePointMap;
-	private Map<LayerInfo, LayerContents> layerMap;
+	private final Map<LayerInfo, LayerContents> layerMap;
 	private List<LayerContents> layers;
-	
+
 	public PathOptimizer()
 	{
@@ -30,7 +30,7 @@
 			this.uniquePointMap.put(point, point);
 			return point;
-		}		
-	}
-	
+		}
+	}
+
 	public void addPath(LayerInfo info, PdfPath path)
 	{
@@ -38,14 +38,14 @@
 		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);					
-	}	
-	
+		layer.multiPaths.add(p);
+	}
+
 	private LayerContents getLayer(LayerInfo info) {
 		LayerContents layer;
-		
+
 		if (this.layerMap.containsKey(info))
 		{
@@ -63,17 +63,17 @@
 		return layer;
 	}
-	
+
 	public void optimize()
 	{
 		for(LayerContents layer: this.layers) {
-			this.optimizeLayer(layer);			
-		}
-		
+			this.concatenataPaths(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;
@@ -82,7 +82,7 @@
 			}
 		}
-		
+
 		this.layers = newLayers;
-		
+
 		for(LayerContents layer: this.layers) {
 			finalizeLayer(layer);
@@ -93,8 +93,8 @@
 		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)) {
@@ -102,12 +102,12 @@
 					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)) {
@@ -119,68 +119,44 @@
 		}
 	}
-	
+
 	/**
-	 * This method merges together paths with common end nodes. 
+	 * This method merges together paths with common end nodes.
 	 * @param layer the layer to process.
 	 */
-	private void optimizeLayer(LayerContents layer) {
+	private void concatenataPaths(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;
-				}
-			}
-			
-		});
-		*/
-	
+		Set<PdfPath> mergedPaths = new HashSet<PdfPath>();
+
 		for(PdfPath pp: layer.paths){
-						
+
 			PdfPath path = pp;
 			boolean changed = true;
-			
+
 			while (changed && !path.isClosed()) {
 				changed  = false;
-				
-				if (pathEndpoints.containsKey(path.firstPoint())){					
+
+				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;									
+					path.points = newNodes;
 					mergedPaths.add(p1);
 					changed = true;
 				}
-				
-				if (pathEndpoints.containsKey(path.lastPoint())){					
+
+				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;									
+					path.points = newNodes;
 					mergedPaths.add(p1);
 					changed = true;
-				}				
-			}	
-			
+				}
+			}
+
 			if (!path.isClosed()){
 				pathEndpoints.put(path.firstPoint(), path);
@@ -188,7 +164,7 @@
 			}
 		}
-		
+
 		List<PdfPath> resultPaths = new ArrayList<PdfPath>();
-		
+
 		for(PdfPath path: layer.paths) {
 			if (!mergedPaths.contains(path)){
@@ -196,8 +172,8 @@
 			}
 		}
-				
+
 		layer.paths = resultPaths;
 	}
-	
+
 	private List<LayerContents> splitBySegmentKind(LayerContents layer)
 	{
@@ -205,5 +181,5 @@
 		List<PdfPath> multiSegmentPaths = new ArrayList<PdfPath>();
 		List<PdfPath> closedPaths = new ArrayList<PdfPath>();
-		
+
 		for(PdfPath path: layer.paths) {
 			if (path.points.size() <= 3) {
@@ -217,15 +193,15 @@
 			}
 		}
-		
+
 		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();
@@ -242,19 +218,19 @@
 			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);
@@ -267,18 +243,18 @@
 				nodes1.add(nodes2.get(pos));
 			}
-			
-			return nodes1;
-		} 
+
+			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);			
+			nodes1.remove(0);
 			for (int pos = 0; pos < nodes2.size(); pos ++) {
 				nodes1.add(0, nodes2.get(pos));
 			}
-			
+
 			return nodes1;
 		} else {
