rrenkert@243: /* rrenkert@243: * Copyright (c) 2011 by Intevation GmbH, Germany rrenkert@243: * rrenkert@243: * This file is part of MXD2map. rrenkert@243: * rrenkert@243: * This program is free software under the LGPL (>=v2.1) rrenkert@243: * Read the file LICENCE.txt coming with the software for details rrenkert@243: * or visit http://www.gnu.org/licenses/ if it does not exist. rrenkert@243: * rrenkert@243: * MXD2map has been developed on behalf of the rrenkert@243: * Bundesamt fuer Seeschifffahrt und Hydrographie (BSH) in Hamburg rrenkert@243: * by Intevation GmbH. rrenkert@243: * rrenkert@243: * Authors: rrenkert@243: * Raimund Renkert rrenkert@243: * Bjoern Schilberg rrenkert@243: * Stephan Holl rrenkert@243: */ rrenkert@243: rrenkert@97: package de.intevation.mxd.writer; rrenkert@97: rrenkert@97: import java.awt.Color; rrenkert@97: import org.apache.log4j.Logger; rrenkert@97: rrenkert@97: import org.w3c.dom.Element; rrenkert@97: import org.w3c.dom.NodeList; rrenkert@97: rrenkert@97: import edu.umn.gis.mapscript.mapObj; rrenkert@97: import edu.umn.gis.mapscript.classObj; rrenkert@97: import edu.umn.gis.mapscript.styleObj; rrenkert@97: import edu.umn.gis.mapscript.colorObj; rrenkert@97: import edu.umn.gis.mapscript.symbolSetObj; rrenkert@97: rrenkert@97: /** rrenkert@97: * The interface to the mapfile writer. rrenkert@97: * rrenkert@97: * @author Raimund Renkert rrenkert@97: */ rrenkert@97: public class FillStyleWriter { rrenkert@97: rrenkert@97: /** rrenkert@97: * The Logger. rrenkert@97: */ rrenkert@97: private static final Logger logger = rrenkert@97: Logger.getLogger(FillStyleWriter.class); rrenkert@97: rrenkert@181: /** rrenkert@181: * Private member. rrenkert@181: */ rrenkert@97: private mapObj map; rrenkert@97: private classObj cl; rrenkert@97: private styleObj style; vc11884admin@150: private colorObj fill; rrenkert@97: rrenkert@181: /** rrenkert@181: * Constructor with map object and class object. rrenkert@181: * rrenkert@181: * @param map The map object. rrenkert@181: * @param cl The class object containing the style. rrenkert@181: */ rrenkert@97: public FillStyleWriter (mapObj map, classObj cl) { aheinecke@336: logger.debug("constructor(mapObj, classObj)"); rrenkert@97: this.map = map; rrenkert@97: this.cl = cl; rrenkert@97: this.style = new styleObj(cl); rrenkert@97: } rrenkert@97: rrenkert@97: /** rrenkert@97: * Write the content. rrenkert@181: * rrenkert@181: * @param symbolElement DOM element containing style attributes. rrenkert@97: */ rrenkert@120: public boolean write(Element symbolElement) { raimund@251: logger.debug("write(Element)"); rrenkert@97: symbolSetObj symbolSet = map.getSymbolset(); rrenkert@97: rrenkert@97: if(symbolElement.hasChildNodes()) { rrenkert@97: NodeList symbols = symbolElement.getChildNodes(); rrenkert@97: for (int i = 0; i < symbols.getLength(); i++) { rrenkert@97: Element nextSym = (Element)symbols.item(i); rrenkert@97: String type = nextSym.getAttribute("type"); rrenkert@97: if(((symbols.getLength() > 1 && i == 0) || rrenkert@97: (symbols.getLength() == 1 && rrenkert@97: !symbolElement.hasAttribute("hatch"))) && rrenkert@97: type.equals("line")) { vc11884admin@150: if(symbolElement.hasAttribute("color")) { vc11884admin@150: Color oCol = Color.decode( vc11884admin@150: symbolElement.getAttribute("color")); vc11884admin@150: fill = new colorObj( vc11884admin@150: oCol.getRed(), vc11884admin@150: oCol.getGreen(), vc11884admin@150: oCol.getBlue(), vc11884admin@150: -4); vc11884admin@150: } rrenkert@97: writeOutline(nextSym); rrenkert@97: if (symbols.getLength() == 1) { raimund@251: String stype = symbolElement.getAttribute("style"); raimund@251: if(stype.equals("picture")) { raimund@251: double gap = 0; raimund@251: if(symbolElement.hasAttribute("xseparation")) { raimund@251: try { raimund@251: gap = Double.parseDouble( raimund@251: symbolElement.getAttribute("xseparation")); raimund@251: } raimund@251: catch(NumberFormatException nfe) { raimund@251: gap = 0; raimund@251: } raimund@251: } raimund@251: raimund@251: try { raimund@251: SymbolWriter sw = raimund@251: new SymbolWriter(this.map, this.cl); raimund@251: sw.write(symbolElement); raimund@251: sw.saveSymbolSet(symbolSet); raimund@251: } raimund@251: catch(Exception e) { raimund@251: logger.warn("Could not save symbol set."); raimund@251: } raimund@251: writeMarker(symbolElement, gap); raimund@251: } raimund@251: else { raimund@251: writeSimple(symbolElement); raimund@251: try { raimund@251: SymbolWriter sw = raimund@251: new SymbolWriter(this.map, this.cl); raimund@251: sw.saveSymbolSet(symbolSet); raimund@251: } raimund@251: catch(Exception e) { raimund@251: logger.warn("Could not save symbol set."); raimund@251: } raimund@251: } raimund@184: } rrenkert@97: } rrenkert@97: else if(nextSym.getTagName().equals("symbol") && rrenkert@97: !symbolElement.hasAttribute("hatch") || rrenkert@97: (i == 1 && type.equals("marker"))) { rrenkert@97: double gap = 0; rrenkert@97: if(symbolElement.hasAttribute("xseparation")) { rrenkert@145: try { rrenkert@145: gap = Double.parseDouble( rrenkert@145: symbolElement.getAttribute("xseparation")); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: gap = 0; rrenkert@145: } rrenkert@97: } rrenkert@97: writeMarker(nextSym, gap); rrenkert@97: } rrenkert@97: else if (nextSym.getTagName().equals("symbol") && rrenkert@97: symbolElement.hasAttribute("hatch")) { vc11884admin@168: if(i == 0) { vc11884admin@168: writeOutline(nextSym); rrenkert@97: } vc11884admin@168: else { vc11884admin@168: if(symbolElement.hasAttribute("angle")) { vc11884admin@168: nextSym.setAttribute( vc11884admin@168: "angle", vc11884admin@168: symbolElement.getAttribute("angle")); vc11884admin@168: } vc11884admin@168: if(symbolElement.hasAttribute("separation")) { vc11884admin@168: nextSym.setAttribute( vc11884admin@168: "size", vc11884admin@168: symbolElement.getAttribute("separation")); vc11884admin@168: } vc11884admin@168: writeMarker(nextSym, -1); rrenkert@97: } rrenkert@97: } rrenkert@97: else { rrenkert@97: writeSimple(symbolElement); raimund@184: try { raimund@251: SymbolWriter sw = raimund@251: new SymbolWriter(this.map, this.cl); raimund@184: sw.saveSymbolSet(symbolSet); raimund@184: } raimund@184: catch(Exception e) { raimund@184: logger.warn("Could not save symbol set."); raimund@184: } rrenkert@97: } rrenkert@97: } rrenkert@97: } rrenkert@97: else { rrenkert@97: writeSimple(symbolElement); rrenkert@97: if(symbolElement.hasAttribute("outline_color")) { rrenkert@97: Color oCol = Color.decode( rrenkert@97: symbolElement.getAttribute("outline_color")); rrenkert@97: colorObj outlineColor = new colorObj( rrenkert@97: oCol.getRed(), rrenkert@97: oCol.getGreen(), rrenkert@97: oCol.getBlue(), rrenkert@97: -4); rrenkert@97: style.setOutlinecolor(outlineColor); rrenkert@145: try { rrenkert@145: style.setOutlinewidth(Double.parseDouble( rrenkert@145: symbolElement.getAttribute("outline_size"))); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: logger.warn("Error setting outline width."); rrenkert@145: style.setOutlinewidth(0.0); rrenkert@145: } rrenkert@97: } raimund@184: try { raimund@184: SymbolWriter sw = new SymbolWriter(this.map, this.cl); raimund@184: sw.saveSymbolSet(symbolSet); raimund@184: } raimund@184: catch(Exception e) { raimund@184: logger.warn("Could not save symbol set."); raimund@184: } rrenkert@97: } rrenkert@97: return true; rrenkert@97: } rrenkert@97: rrenkert@97: /** rrenkert@97: * Write the outline for a polygon. rrenkert@181: * rrenkert@181: * @param symbolElement Dom element containing the symbol attributes. rrenkert@97: */ rrenkert@120: private void writeOutline(Element symbolElement) { rrenkert@97: logger.debug("writeOutline()"); rrenkert@97: //write transparent outline rrenkert@97: colorObj color = new colorObj(-1, -1, -1, -4); vc11884admin@150: double w = 0; vc11884admin@150: double transp = -1; vc11884admin@131: if(symbolElement.hasAttribute("width")) { rrenkert@145: try { rrenkert@145: w = Double.parseDouble(symbolElement.getAttribute("width")); vc11884admin@167: if(symbolElement.hasAttribute("transparency")) { vc11884admin@167: transp = Double.parseDouble( vc11884admin@167: symbolElement.getAttribute("transparency")); vc11884admin@167: } vc11884admin@167: else { vc11884admin@167: transp = -1; vc11884admin@167: } rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { vc11884admin@150: logger.warn("Error setting outline width or transparency."); rrenkert@145: w = 0; vc11884admin@150: transp = -1; vc11884admin@131: } vc11884admin@131: } rrenkert@180: rrenkert@97: Color oCol = Color.decode( rrenkert@97: symbolElement.getAttribute("color")); rrenkert@97: rrenkert@97: styleObj outline = new styleObj (cl); raimund@242: if (w < 1.0) { vc11884admin@150: symbolElement.setAttribute("width", "1"); vc11884admin@150: } raimund@242: colorObj outlinecolor = new colorObj( raimund@242: oCol.getRed(), raimund@242: oCol.getGreen(), raimund@242: oCol.getBlue(), raimund@242: -4); raimund@242: outline.setOutlinecolor(outlinecolor); raimund@242: if(transp >= 0) { raimund@242: int opacity = (int)((1 - (transp/255)) * 100); raimund@242: outline.setOpacity(opacity); vc11884admin@150: } rrenkert@145: try { rrenkert@145: outline.setOutlinewidth(Double.parseDouble( rrenkert@145: symbolElement.getAttribute("width"))); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: logger.warn("Error setting outline width."); rrenkert@145: outline.setOutlinewidth(0.0); rrenkert@145: } rrenkert@123: if(symbolElement.hasAttribute("linestyle")) { rrenkert@181: //Write predefined dashed or dotted lines. rrenkert@123: String ls = symbolElement.getAttribute("linestyle"); rrenkert@123: double[] vals; rrenkert@123: if(ls.equals("dash")) { rrenkert@123: outline.setPatternlength(2); rrenkert@123: vals = new double[] {4.0, 4.0, 0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: outline.setPattern(vals); rrenkert@123: } rrenkert@123: else if(ls.equals("dot")) { rrenkert@123: outline.setPatternlength(2); rrenkert@123: vals = new double[] {1.0, 3.0, 0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: outline.setPattern(vals); rrenkert@123: } rrenkert@123: else if(ls.equals("dashdot")) { rrenkert@123: outline.setPatternlength(4); rrenkert@123: vals = new double[] {4.0, 3.0, 1.0, 3.0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: outline.setPattern(vals); rrenkert@123: } rrenkert@123: else if (ls.equals("dashdotdot")) { rrenkert@123: outline.setPatternlength(6); rrenkert@123: vals = new double[] {5.0, 3.0, 1.0, 3.0, 1.0, 4.0, 0, 0, 0, 0}; rrenkert@123: outline.setPattern(vals); rrenkert@123: } rrenkert@123: } vc11884admin@167: else if(symbolElement.hasAttribute("pattern_count")) { rrenkert@181: //Write dashed or dotted lines defined with a template. vc11884admin@167: int count = 0; vc11884admin@167: try { vc11884admin@167: count = Integer.parseInt( vc11884admin@167: symbolElement.getAttribute("pattern_count")); vc11884admin@167: double[] vals = new double[10]; vc11884admin@167: double move = 0.0; vc11884admin@167: int pos = 0; vc11884admin@167: for(int i = 0; i < count; i++) { vc11884admin@167: double mark = vc11884admin@167: Double.parseDouble(symbolElement.getAttribute("mark_" + i)); vc11884admin@167: double gap = vc11884admin@167: Double.parseDouble(symbolElement.getAttribute("gap_" + i)); vc11884admin@167: if(i == 0 && mark == 0.0) { vc11884admin@167: move = gap; vc11884admin@167: } vc11884admin@167: else if(i == count - 1 && move > 0.0) { vc11884admin@167: vals[pos++] = mark; vc11884admin@167: vals[pos++] = gap + move; vc11884admin@167: } vc11884admin@167: else { vc11884admin@167: vals[pos++] = mark; vc11884admin@167: vals[pos++] = gap; vc11884admin@167: } vc11884admin@167: } vc11884admin@167: if(move > 0.0) { vc11884admin@167: outline.setPatternlength((count*2) -2); vc11884admin@167: } vc11884admin@167: else { vc11884admin@167: outline.setPatternlength(count*2); vc11884admin@167: } vc11884admin@167: outline.setPattern(vals); rrenkert@123: vc11884admin@167: } vc11884admin@167: catch(NumberFormatException nfe) { vc11884admin@167: logger.warn("Could not write PATTERN."); vc11884admin@167: } vc11884admin@167: } rrenkert@97: } rrenkert@97: rrenkert@97: /** rrenkert@97: * Write marker attributes and a symbol for the polygon fill. rrenkert@181: * rrenkert@181: * @param symbolElement DOM element containingg the symbol attributes. rrenkert@181: * @param gap The initial gap at the begining of a line. rrenkert@97: */ rrenkert@120: private void writeMarker(Element symbolElement, double gap) { rrenkert@97: logger.debug("writeMarker()"); rrenkert@97: String name = symbolElement.getAttribute("name"); rrenkert@97: String type = symbolElement.getAttribute("type"); raimund@251: String stype = symbolElement.getAttribute("style"); rrenkert@97: if (symbolElement.hasAttribute("angle")) { rrenkert@145: try { rrenkert@145: style.setAngle( rrenkert@145: Double.parseDouble(symbolElement.getAttribute("angle"))); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: logger.warn("Error setting angle."); rrenkert@145: style.setAngle(0.0); rrenkert@145: } rrenkert@97: } rrenkert@97: if(symbolElement.hasAttribute("color")) { rrenkert@97: String c = symbolElement.getAttribute("color"); rrenkert@97: Color col = Color.decode(c); rrenkert@97: colorObj color = new colorObj( rrenkert@97: col.getRed(), rrenkert@97: col.getGreen(), rrenkert@97: col.getBlue(), rrenkert@97: -4); rrenkert@97: style.setColor(color); rrenkert@97: } rrenkert@97: if (symbolElement.hasAttribute ("size")) { rrenkert@145: double size = 1; rrenkert@145: try { rrenkert@145: size = Double.parseDouble(symbolElement.getAttribute("size")); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: size = 1.0; rrenkert@145: } rrenkert@97: style.setSize(size); rrenkert@97: //In arcgis the separation goes from center to center, so the gap is rrenkert@97: //the separation - size rrenkert@97: if (gap > 0) { rrenkert@97: style.setGap(gap - size); rrenkert@97: } rrenkert@97: } vc11884admin@168: if(symbolElement.hasAttribute("width")) { vc11884admin@168: double width = 1; vc11884admin@168: try { vc11884admin@168: width = Double.parseDouble(symbolElement.getAttribute("width")); vc11884admin@168: } vc11884admin@168: catch(NumberFormatException nfe) { vc11884admin@168: width = 1.0; vc11884admin@168: } vc11884admin@168: style.setWidth(width); vc11884admin@168: } rrenkert@97: if(symbolElement.hasAttribute("outline_color")) { rrenkert@97: Color oCol = Color.decode( rrenkert@97: symbolElement.getAttribute("outline_color")); rrenkert@97: colorObj outlineColor = new colorObj( rrenkert@97: oCol.getRed(), rrenkert@97: oCol.getGreen(), rrenkert@97: oCol.getBlue(), rrenkert@97: -4); rrenkert@97: style.setOutlinecolor(outlineColor); rrenkert@145: try { rrenkert@145: style.setOutlinewidth(Double.parseDouble( rrenkert@145: symbolElement.getAttribute("outline_size"))); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: logger.warn("Error setting angle."); rrenkert@145: style.setOutlinewidth(0.0); rrenkert@145: } rrenkert@97: } rrenkert@97: if(type.equals("marker")) { rrenkert@97: style.setSymbolByName(map, name); rrenkert@97: SymbolWriter sw = new SymbolWriter(this.map, this.cl); rrenkert@97: sw.write(symbolElement); rrenkert@97: } rrenkert@97: else if(type.equals("line")) { rrenkert@97: style.setSymbolByName(map, "hatch"); rrenkert@97: SymbolWriter sw = new SymbolWriter(this.map, this.cl); rrenkert@97: symbolElement.setAttribute("name", "hatch"); rrenkert@97: sw.write(symbolElement); rrenkert@123: if(symbolElement.hasAttribute("linestyle")) { rrenkert@123: String ls = symbolElement.getAttribute("linestyle"); rrenkert@123: double[] vals; rrenkert@123: if(ls.equals("dash")) { rrenkert@123: style.setPatternlength(2); rrenkert@123: vals = new double[] {4.0, 4.0, 0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: style.setPattern(vals); rrenkert@123: } rrenkert@123: else if(ls.equals("dot")) { rrenkert@123: style.setPatternlength(2); rrenkert@123: vals = new double[] {1.0, 3.0, 0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: style.setPattern(vals); rrenkert@123: } rrenkert@123: else if(ls.equals("dashdot")) { rrenkert@123: style.setPatternlength(4); rrenkert@123: vals = new double[] {4.0, 3.0, 1.0, 3.0, 0, 0, 0, 0, 0, 0, 0}; rrenkert@123: style.setPattern(vals); rrenkert@123: } rrenkert@123: else if (ls.equals("dashdotdot")) { rrenkert@123: style.setPatternlength(6); rrenkert@123: vals = new double[] {5.0, 3.0, 1.0, 3.0, 1.0, 4.0, 0, 0, 0, 0}; rrenkert@123: style.setPattern(vals); rrenkert@123: } rrenkert@123: } rrenkert@97: } raimund@251: if(stype.equals("picture")) { raimund@251: style.setSymbolByName(map, name); raimund@251: } rrenkert@97: } rrenkert@97: rrenkert@97: /** rrenkert@97: * Write simple fill attributes. rrenkert@181: * rrenkert@181: * @param symbolElement DOM element containing the symbol attributes. rrenkert@97: */ rrenkert@97: private void writeSimple(Element symbolElement) { rrenkert@97: logger.debug("writeSimple(Element)"); rrenkert@97: if(symbolElement.hasAttribute("transparency")) { rrenkert@145: double value = 0; rrenkert@145: try { rrenkert@145: value = Double.parseDouble( rrenkert@145: symbolElement.getAttribute("transparency")); rrenkert@145: } rrenkert@145: catch(NumberFormatException nfe) { rrenkert@145: value = 0; rrenkert@145: } raimund@240: int opacity = (int)(1 - (value/255)) * 100; raimund@240: style.setOpacity(opacity); rrenkert@97: } rrenkert@97: if(symbolElement.hasAttribute("color")) { rrenkert@97: String c = symbolElement.getAttribute("color"); rrenkert@97: Color col = Color.decode(c); rrenkert@97: colorObj color = new colorObj( rrenkert@97: col.getRed(), rrenkert@97: col.getGreen(), rrenkert@97: col.getBlue(), rrenkert@97: -4); rrenkert@97: style.setColor(color); rrenkert@97: } rrenkert@97: } rrenkert@97: } rrenkert@97: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :