| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You 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.apache.batik.ext.awt.g2d; |
| |
| import java.awt.geom.AffineTransform; |
| |
| /** |
| * Contains a description of an elementary transform stack element, |
| * such as a rotate or translate. A transform stack element has a |
| * type and a value, which is an array of double values.<br> |
| * |
| * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a> |
| * @author <a href="mailto:paul_evenblij@compuware.com">Paul Evenblij</a> |
| * @version $Id$ |
| */ |
| public abstract class TransformStackElement implements Cloneable{ |
| |
| /** |
| * Transform type |
| */ |
| private TransformType type; |
| |
| /** |
| * Value |
| */ |
| private double[] transformParameters; |
| |
| /** |
| * @param type transform type |
| * @param transformParameters parameters for transform |
| */ |
| protected TransformStackElement(TransformType type, |
| double[] transformParameters){ |
| this.type = type; |
| this.transformParameters = transformParameters; |
| } |
| |
| /** |
| * @return an object which is a deep copy of this one |
| */ |
| public Object clone() { |
| TransformStackElement newElement = null; |
| |
| // start with a shallow copy to get our implementations right |
| try { |
| newElement = (TransformStackElement) super.clone(); |
| } catch(java.lang.CloneNotSupportedException ex) {} |
| |
| // now deep copy the parameter array |
| double[] transformParameters = new double[this.transformParameters.length]; |
| System.arraycopy(this.transformParameters, 0, transformParameters, 0, transformParameters.length); |
| newElement.transformParameters = transformParameters; |
| return newElement; |
| } |
| |
| /* |
| * Factory methods |
| */ |
| |
| public static TransformStackElement createTranslateElement(double tx, |
| double ty){ |
| return new TransformStackElement(TransformType.TRANSLATE, |
| new double[]{ tx, ty }) { |
| boolean isIdentity(double[] parameters) { |
| return parameters[0] == 0 && parameters[1] == 0; |
| } |
| }; |
| } |
| |
| public static TransformStackElement createRotateElement(double theta){ |
| return new TransformStackElement(TransformType.ROTATE, |
| new double[]{ theta }) { |
| boolean isIdentity(double[] parameters) { |
| return Math.cos(parameters[0]) == 1; |
| } |
| }; |
| } |
| |
| public static TransformStackElement createScaleElement(double scaleX, |
| double scaleY){ |
| return new TransformStackElement(TransformType.SCALE, |
| new double[]{ scaleX, scaleY }) { |
| boolean isIdentity(double[] parameters) { |
| return parameters[0] == 1 && parameters[1] == 1; |
| } |
| }; |
| } |
| |
| public static TransformStackElement createShearElement(double shearX, |
| double shearY){ |
| return new TransformStackElement(TransformType.SHEAR, |
| new double[]{ shearX, shearY }) { |
| boolean isIdentity(double[] parameters) { |
| return parameters[0] == 0 && parameters[1] == 0; |
| } |
| }; |
| } |
| |
| public static TransformStackElement createGeneralTransformElement |
| (AffineTransform txf){ |
| double[] matrix = new double[6]; |
| txf.getMatrix(matrix); |
| return new TransformStackElement(TransformType.GENERAL, matrix) { |
| boolean isIdentity(double[] m) { |
| return (m[0] == 1 && m[2] == 0 && m[4] == 0 && |
| m[1] == 0 && m[3] == 1 && m[5] == 0); |
| } |
| }; |
| } |
| |
| /** |
| * Implementation should determine if the parameter list represents |
| * an identity transform, for the instance transform type. |
| */ |
| abstract boolean isIdentity(double[] parameters); |
| |
| /** |
| * @return true iff this transform is the identity transform |
| */ |
| public boolean isIdentity() { |
| return isIdentity(transformParameters); |
| } |
| |
| /** |
| * @return array of values containing this transform element's parameters |
| */ |
| public double[] getTransformParameters(){ |
| return transformParameters; |
| } |
| |
| /** |
| * @return this transform type |
| */ |
| public TransformType getType(){ |
| return type; |
| } |
| |
| /* |
| * Concatenation utility. Requests this transform stack element |
| * to concatenate with the input stack element. Only elements |
| * of the same types are concatenated. For example, if this |
| * element represents a translation, it will concatenate with |
| * another translation, but not with any other kind of |
| * stack element. |
| * @param stackElement element to be concatenated with this one. |
| * @return true if the input stackElement was concatenated with |
| * this one. False otherwise. |
| */ |
| public boolean concatenate(TransformStackElement stackElement){ |
| boolean canConcatenate = false; |
| |
| if(type.toInt() == stackElement.type.toInt()){ |
| canConcatenate = true; |
| switch(type.toInt()){ |
| case TransformType.TRANSFORM_TRANSLATE: |
| transformParameters[0] += stackElement.transformParameters[0]; |
| transformParameters[1] += stackElement.transformParameters[1]; |
| break; |
| case TransformType.TRANSFORM_ROTATE: |
| transformParameters[0] += stackElement.transformParameters[0]; |
| break; |
| case TransformType.TRANSFORM_SCALE: |
| transformParameters[0] *= stackElement.transformParameters[0]; |
| transformParameters[1] *= stackElement.transformParameters[1]; |
| break; |
| case TransformType.TRANSFORM_GENERAL: |
| transformParameters |
| = matrixMultiply(transformParameters, |
| stackElement.transformParameters); |
| break; |
| default: |
| canConcatenate = false; |
| } |
| } |
| |
| return canConcatenate; |
| } |
| |
| /** |
| * Multiplies two 2x3 matrices of double precision values |
| */ |
| private double[] matrixMultiply(double[] matrix1, double[] matrix2) { |
| double[] product = new double[6]; |
| AffineTransform transform1 = new AffineTransform(matrix1); |
| transform1.concatenate(new AffineTransform(matrix2)); |
| transform1.getMatrix(product); |
| return product; |
| } |
| |
| } |