001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.bridge;
020:
021: import java.awt.geom.AffineTransform;
022: import java.awt.geom.Rectangle2D;
023:
024: import org.apache.batik.ext.awt.image.renderable.Filter;
025: import org.apache.batik.gvt.CompositeGraphicsNode;
026: import org.apache.batik.gvt.GraphicsNode;
027: import org.apache.batik.gvt.filter.Mask;
028: import org.apache.batik.gvt.filter.MaskRable8Bit;
029: import org.w3c.dom.Element;
030: import org.w3c.dom.Node;
031:
032: /**
033: * Bridge class for the <mask> element.
034: *
035: * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
036: * @version $Id: SVGMaskElementBridge.java 475477 2006-11-15 22:44:28Z cam $
037: */
038: public class SVGMaskElementBridge extends AnimatableGenericSVGBridge
039: implements MaskBridge {
040:
041: /**
042: * Constructs a new bridge for the <mask> element.
043: */
044: public SVGMaskElementBridge() {
045: }
046:
047: /**
048: * Returns 'mask'.
049: */
050: public String getLocalName() {
051: return SVG_MASK_TAG;
052: }
053:
054: /**
055: * Creates a <tt>Mask</tt> according to the specified parameters.
056: *
057: * @param ctx the bridge context to use
058: * @param maskElement the element that defines the mask
059: * @param maskedElement the element that references the mask element
060: * @param maskedNode the graphics node to mask
061: */
062: public Mask createMask(BridgeContext ctx, Element maskElement,
063: Element maskedElement, GraphicsNode maskedNode) {
064:
065: String s;
066:
067: // get mask region using 'maskUnits'
068: Rectangle2D maskRegion = SVGUtilities.convertMaskRegion(
069: maskElement, maskedElement, maskedNode, ctx);
070:
071: //
072: // Build the GVT tree that represents the mask
073: //
074: GVTBuilder builder = ctx.getGVTBuilder();
075: CompositeGraphicsNode maskNode = new CompositeGraphicsNode();
076: CompositeGraphicsNode maskNodeContent = new CompositeGraphicsNode();
077: maskNode.getChildren().add(maskNodeContent);
078: boolean hasChildren = false;
079: for (Node node = maskElement.getFirstChild(); node != null; node = node
080: .getNextSibling()) {
081:
082: // check if the node is a valid Element
083: if (node.getNodeType() != Node.ELEMENT_NODE) {
084: continue;
085: }
086:
087: Element child = (Element) node;
088: GraphicsNode gn = builder.build(ctx, child);
089: if (gn == null) {
090: continue;
091: }
092: hasChildren = true;
093: maskNodeContent.getChildren().add(gn);
094: }
095: if (!hasChildren) {
096: return null; // empty mask
097: }
098:
099: // 'transform' attribute
100: AffineTransform Tx;
101: s = maskElement.getAttributeNS(null, SVG_TRANSFORM_ATTRIBUTE);
102: if (s.length() != 0) {
103: Tx = SVGUtilities.convertTransform(maskElement,
104: SVG_TRANSFORM_ATTRIBUTE, s, ctx);
105: } else {
106: Tx = new AffineTransform();
107: }
108:
109: // 'maskContentUnits' attribute - default is userSpaceOnUse
110: short coordSystemType;
111: s = maskElement.getAttributeNS(null,
112: SVG_MASK_CONTENT_UNITS_ATTRIBUTE);
113: if (s.length() == 0) {
114: coordSystemType = SVGUtilities.USER_SPACE_ON_USE;
115: } else {
116: coordSystemType = SVGUtilities.parseCoordinateSystem(
117: maskElement, SVG_MASK_CONTENT_UNITS_ATTRIBUTE, s,
118: ctx);
119: }
120:
121: // additional transform to move to objectBoundingBox coordinate system
122: if (coordSystemType == SVGUtilities.OBJECT_BOUNDING_BOX) {
123: Tx = SVGUtilities.toObjectBBox(Tx, maskedNode);
124: }
125:
126: maskNodeContent.setTransform(Tx);
127:
128: Filter filter = maskedNode.getFilter();
129: if (filter == null) {
130: // Make the initial source as a RenderableImage
131: filter = maskedNode.getGraphicsNodeRable(true);
132: }
133:
134: return new MaskRable8Bit(filter, maskNode, maskRegion);
135: }
136: }
|