// Copyright 2001-2004, FreeHEP. package org.freehep.postscript; import java.awt.geom.AffineTransform; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; /** * Matrix Operators for PostScript Processor * * @author Mark Donszelmann * @version $Id: MatrixOperator.java 8958 2006-09-12 23:37:43Z duns $ */ public class MatrixOperator extends PSOperator { public static Class[] operators = { Matrix.class, InitMatrix.class, IdentMatrix.class, DefaultMatrix.class, CurrentMatrix.class, SetMatrix.class, Translate.class, Scale.class, Rotate.class, Concat.class, ConcatMatrix.class, Transform.class, DTransform.class, ITransform.class, IDTransform.class, InvertMatrix.class }; public boolean execute(OperandStack os) { throw new RuntimeException("Cannot execute class: "+getClass()); } } class Matrix extends MatrixOperator { public boolean execute(OperandStack os) { os.push(new PSArray(new double[] { 1, 0, 0, 1, 0, 0 })); return true; } } class InitMatrix extends MatrixOperator { public boolean execute(OperandStack os) { os.gstate().setTransform(new AffineTransform()); return true; } } class IdentMatrix extends MatrixOperator { { operandTypes = new Class[] {PSArray.class}; } public boolean execute(OperandStack os) { PSArray a = os.popArray(); a.set(new double[] { 1, 0, 0, 1, 0, 0 }); os.push(a); return true; } } class DefaultMatrix extends MatrixOperator { { operandTypes = new Class[] {PSArray.class}; } public boolean execute(OperandStack os) { PSArray a = os.popArray(); double[] d = { 1, 0, 0, 1, 0, 0}; a.set(d); os.push(a); return true; } } class CurrentMatrix extends MatrixOperator { { operandTypes = new Class[] {PSArray.class}; } public boolean execute(OperandStack os) { PSArray a = os.popArray(); if (a.size() < 6) { error(os, new RangeCheck()); } else { AffineTransform ctm = os.gstate().getTransform(); double[] m = new double[6]; ctm.getMatrix(m); a.set(m); os.push(a); } return true; } } class SetMatrix extends MatrixOperator { { operandTypes = new Class[] {PSPackedArray.class}; } public boolean execute(OperandStack os) { PSPackedArray a = os.popPackedArray(); AffineTransform ctm = new AffineTransform(a.toDoubles()); os.gstate().setTransform(ctm); return true; } } class Translate extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { if (os.checkType(PSNumber.class, PSNumber.class)) { double ty = os.popNumber().getDouble(); double tx = os.popNumber().getDouble(); os.gstate().translate(tx, ty); } else if (os.checkType(PSNumber.class, PSNumber.class, PSArray.class)) { PSArray a = os.popArray(); if (a.size() >= 6) { PSNumber ty = os.popNumber(); PSNumber tx = os.popNumber(); a.set(0, 1); a.set(1, 0); a.set(2, 0); a.set(3, 1); a.set(4, tx); a.set(5, ty); os.push(a); } else { error(os, new RangeCheck()); } } else { error(os, new TypeCheck()); } return true; } } class Scale extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { if (os.checkType(PSNumber.class, PSNumber.class)) { double sy = os.popNumber().getDouble(); double sx = os.popNumber().getDouble(); os.gstate().scale(sx, sy); } else if (os.checkType(PSNumber.class, PSNumber.class, PSArray.class)) { PSArray a = os.popArray(); if (a.size() >= 6) { PSNumber sy = os.popNumber(); PSNumber sx = os.popNumber(); a.set(0, sx); a.set(1, 0); a.set(2, 0); a.set(3, sy); a.set(4, 0); a.set(5, 0); os.push(a); } else { error(os, new RangeCheck()); } } else { error(os, new TypeCheck()); } return true; } } class Rotate extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { if (os.checkType(PSNumber.class)) { double angle = os.popNumber().getDouble(); os.gstate().rotate(Math.toRadians(angle)); } else if (os.checkType(PSNumber.class, PSArray.class)) { PSArray a = os.popArray(); if (a.size() >= 6) { double theta = Math.toRadians(os.popNumber().getDouble()); double sinTheta = Math.sin(theta); double cosTheta = Math.cos(theta); a.set(0, cosTheta); a.set(1, sinTheta); a.set(2, -sinTheta); a.set(3, cosTheta); a.set(4, 0); a.set(5, 0); os.push(a); } else { error(os, new RangeCheck()); } } else { error(os, new TypeCheck()); } return true; } } class Concat extends MatrixOperator { { operandTypes = new Class[] {PSPackedArray.class}; } public boolean execute(OperandStack os) { AffineTransform m = new AffineTransform(os.popPackedArray().toDoubles()); os.gstate().transform(m); return true; } } class ConcatMatrix extends MatrixOperator { { operandTypes = new Class[] {PSPackedArray.class, PSPackedArray.class, PSArray.class}; } public boolean execute(OperandStack os) { PSArray m3 = os.popArray(); PSPackedArray m2 = os.popPackedArray(); PSPackedArray m1 = os.popPackedArray(); AffineTransform t = new AffineTransform(m1.toDoubles()); t.concatenate(new AffineTransform(m2.toDoubles())); double[] d = new double[6]; t.getMatrix(d); m3.set(d); os.push(m3); return true; } } class Transform extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { AffineTransform transform; double dx, dy; if (os.checkType(PSNumber.class, PSNumber.class)) { dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = os.gstate().getTransform(); } else if (os.checkType(PSNumber.class, PSNumber.class, PSPackedArray.class)) { double[] m = os.popPackedArray().toDoubles(); dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = new AffineTransform(m); } else { error(os, new TypeCheck()); return true; } Point2D d = transform.transform(new Point2D.Double(dx, dy), null); os.push(d.getX()); os.push(d.getY()); return true; } } class DTransform extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { AffineTransform transform; double dx, dy; if (os.checkType(PSNumber.class, PSNumber.class)) { dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = os.gstate().getTransform(); } else if (os.checkType(PSNumber.class, PSNumber.class, PSPackedArray.class)) { double[] m = os.popPackedArray().toDoubles(); dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = new AffineTransform(m); } else { error(os, new TypeCheck()); return true; } Point2D d = transform.deltaTransform(new Point2D.Double(dx, dy), null); os.push(d.getX()); os.push(d.getY()); return true; } } class ITransform extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { AffineTransform transform; double dx, dy; if (os.checkType(PSNumber.class, PSNumber.class)) { dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = os.gstate().getTransform(); } else if (os.checkType(PSNumber.class, PSNumber.class, PSPackedArray.class)) { double[] m = os.popPackedArray().toDoubles(); dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = new AffineTransform(m); } else { error(os, new TypeCheck()); return true; } try { Point2D d = transform.inverseTransform(new Point2D.Double(dx, dy), null); os.push(d.getX()); os.push(d.getY()); } catch (NoninvertibleTransformException e) { error(os, new UndefinedResult()); } return true; } } class IDTransform extends MatrixOperator { { operandTypes = new Class[] {PSObject.class}; } public boolean execute(OperandStack os) { AffineTransform transform; double dx, dy; if (os.checkType(PSNumber.class, PSNumber.class)) { dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = os.gstate().getTransform(); } else if (os.checkType(PSNumber.class, PSNumber.class, PSPackedArray.class)) { double[] m = os.popPackedArray().toDoubles(); dy = os.popNumber().getDouble(); dx = os.popNumber().getDouble(); transform = new AffineTransform(m); } else { error(os, new TypeCheck()); return true; } try { AffineTransform inverse = transform.createInverse(); Point2D d = inverse.deltaTransform(new Point2D.Double(dx, dy), null); os.push(d.getX()); os.push(d.getY()); } catch (NoninvertibleTransformException e) { error(os, new UndefinedResult()); } return true; } } class InvertMatrix extends MatrixOperator { { operandTypes = new Class[] {PSPackedArray.class, PSArray.class}; } public boolean execute(OperandStack os) { PSArray m2 = os.popArray(); PSPackedArray m1 = os.popPackedArray(); try { AffineTransform transform = new AffineTransform(m1.toDoubles()); AffineTransform inverse = transform.createInverse(); double[] d = new double[6]; inverse.getMatrix(d); m2.set(d); os.push(m2); } catch (NoninvertibleTransformException e) { error(os, new UndefinedResult()); } return true; } }