/******************************************************************************* * Copyright 2010 Simon Mieth * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package org.kabeja.svg.generators; import java.util.HashMap; import java.util.Map; import org.kabeja.common.Color; import org.kabeja.common.DraftEntity; import org.kabeja.common.Layer; import org.kabeja.common.LineType; import org.kabeja.common.LineWidth; import org.kabeja.common.Type; import org.kabeja.entities.Viewport; import org.kabeja.math.Bounds; import org.kabeja.math.Point3D; import org.kabeja.math.TransformContext; import org.kabeja.svg.SVGConstants; import org.kabeja.svg.SVGContext; import org.kabeja.svg.SVGGenerationException; import org.kabeja.svg.SVGSAXGenerator; import org.kabeja.svg.SVGSAXGeneratorManager; import org.kabeja.svg.SVGUtils; import org.kabeja.util.Constants; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; public class SVGViewportGenerator extends AbstractSVGSAXGenerator { private SVGSAXGeneratorManager manager; public void toSAX(ContentHandler handler, Map svgContext, DraftEntity entity, TransformContext transformContext) throws SAXException { Viewport viewport = (Viewport) entity; // make a copy of the context svgContext = new HashMap(svgContext); if (viewport.getViewportStatus() > 0) { Point3D center = viewport.getCenterPoint(); AttributesImpl attr = new AttributesImpl(); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_X, "" + SVGUtils.formatNumberAttribute((center.getX() - (viewport .getWidth() / 2)))); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_Y, "" + SVGUtils.formatNumberAttribute((center.getY() - (viewport .getHeight() / 2)))); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_WIDTH, "" + SVGUtils.formatNumberAttribute(viewport.getWidth())); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_HEIGHT, "" + SVGUtils.formatNumberAttribute(viewport.getHeight())); super.setCommonAttributes(attr, svgContext, entity); SVGUtils.emptyElement(handler, SVGConstants.SVG_RECTANLGE, attr); if (!viewport.isModelSpace() && !viewport.getViewportID().equals("1")) { attr = new AttributesImpl(); // first the clip path SVGUtils.addAttribute(attr, SVGConstants.XML_ID, SVGUtils .validateID(viewport.getID() + "_clip")); SVGUtils.startElement(handler, SVGConstants.SVG_CLIPPING_PATH, attr); Bounds viewBounds = viewport.getModelspaceViewBounds(); attr = new AttributesImpl(); double w = viewBounds.getWidth() / 2; double h = viewBounds.getHeight() / 2; Point3D p = viewport.getViewCenterPoint(); StringBuffer buf = new StringBuffer(); buf.append('M'); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getX() - w))); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getY() - h))); buf.append(' '); buf.append('L'); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getX() + w))); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getY() - h))); buf.append(' '); buf.append('L'); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getX() + w))); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getY() + h))); buf.append(' '); buf.append('L'); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getX() - w))); buf.append(' '); buf.append(SVGUtils.formatNumberAttribute((p.getY() + h))); buf.append(' '); buf.append('z'); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_VIEWBOX, buf.toString()); SVGUtils.addAttribute(attr, "d", buf.toString()); SVGUtils.emptyElement(handler, SVGConstants.SVG_PATH, attr); SVGUtils.endElement(handler, SVGConstants.SVG_CLIPPING_PATH); // output the view to modelspace double zoomXP = viewport.getZoomXPFactor(); this.manager = (SVGSAXGeneratorManager) svgContext .get(SVGContext.SVGSAXGENERATOR_MANAGER); attr = new AttributesImpl(); SVGUtils.addAttribute(attr, SVGConstants.XML_ID, SVGUtils .toValidateID(viewport.getID())); // the transform StringBuffer buff = new StringBuffer(); buff.append("translate("); buff.append(' '); buff.append(viewport.getCenterPoint().getX()); buff.append(' '); buff.append(viewport.getCenterPoint().getY()); buff.append(')'); buff.append("scale("); buff.append(zoomXP); buff.append(' '); buff.append(zoomXP); buff.append(')'); buff.append(' '); buff.append("translate("); buff.append(' '); buff.append((-1 * viewport.getViewCenterPoint().getX())); buff.append(' '); buff.append((-1 * viewport.getViewCenterPoint().getY())); buff.append(')'); SVGUtils.addAttribute(attr, "transform", buff.toString()); // the stroke-width double width = 0; LineWidth lw = null; if (svgContext.containsKey(SVGContext.LINE_WIDTH)) { lw = (LineWidth) svgContext .get(SVGContext.LAYER_STROKE_WIDTH); lw.setValue(lw.getValue() / zoomXP); } else { width = (viewBounds.getWidth() + viewBounds.getHeight()) / 2 * SVGConstants.DEFAULT_STROKE_WIDTH_PERCENT; double defaultSW = ((double) Constants.ENVIRONMENT_VARIABLE_LWDEFAULT) / 100.0; if (width > defaultSW) { width = defaultSW; } lw = new LineWidth(); lw.setValue(width); } SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_STROKE_WITDH, SVGUtils .formatNumberAttribute(width)); svgContext.put(SVGContext.LINE_WIDTH, lw); // reference the clip path SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_CLIP_PATH, "url(#" + SVGUtils.validateID(viewport.getID() + "_clip") + ")"); SVGUtils.startElement(handler, SVGConstants.SVG_GROUP, attr); for (Layer layer : viewport.getDocument().getLayers()) { if (!viewport.isFrozenLayer(layer.getName())) { this.layerToSAX(handler, layer, svgContext, viewBounds, viewport); } } SVGUtils.endElement(handler, SVGConstants.SVG_GROUP); } } } protected void layerToSAX(ContentHandler handler, Layer layer, Map context, Bounds viewBounds, Viewport viewport) throws SAXException { AttributesImpl attr = new AttributesImpl(); SVGUtils.addAttribute(attr, SVGConstants.XML_ID, SVGUtils .validateID(layer.getName())); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_COLOR, Color.getRGBString(Math.abs(layer.getColor()))); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_STROKE, SVGConstants.SVG_ATTRIBUTE_VALUE_CURRENTCOLOR); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_FILL, SVGConstants.SVG_ATTRIBUTE_FILL_VALUE_NONE); if (!layer.isVisible()) { SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_VISIBILITY, SVGConstants.SVG_ATTRIBUTE_VISIBILITY_VALUE_HIDDEN); } if (layer.hasLineType()) { LineType ltype = layer.getLineType(); SVGUtils.addStrokeDashArrayAttribute(attr, ltype); } // the stroke-width int lineWeight = layer.getLineWeight(); // the stroke-width LineWidth lw = null; if ((lineWeight > 0) && !context.containsKey(SVGContext.DRAFT_STROKE_WIDTH_IGNORE)) { lw = new LineWidth(LineWidth.TYPE_LINE_WEIGHT, lineWeight); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_STROKE_WITDH, SVGUtils .lineWidthToStrokeWidth(lw)); } else { lw = (LineWidth) context.get(SVGContext.LINE_WIDTH); SVGUtils.addAttribute(attr, SVGConstants.SVG_ATTRIBUTE_STROKE_WITDH, SVGUtils .lineWidthToStrokeWidth(lw)); } context.put(SVGContext.LAYER_STROKE_WIDTH, lw); SVGUtils.startElement(handler, SVGConstants.SVG_GROUP, attr); for (Type<? extends DraftEntity> type : layer.getEntityTypes()) { try { SVGSAXGenerator gen = this.manager.getSVGGenerator(type .getHandle()); for (DraftEntity entity : layer.getEntitiesByType(type)) { Bounds b = entity.getBounds(); // TODO only output the modelspace entities which are inside // or partial the // bounds if (entity.isModelSpace() && b.contains(viewBounds)) { gen.toSAX(handler, context, entity, null); } } } catch (SVGGenerationException e) { e.printStackTrace(); } } SVGUtils.endElement(handler, SVGConstants.SVG_GROUP); } }