/******************************************************************************* * Copyright (c) 2009, Adobe Systems Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Adobe Systems Incorporated nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ package com.adobe.dp.office.vml; import java.util.StringTokenizer; import org.xml.sax.Attributes; public class VMLFElement extends VMLElement { String command; Object[] args; public VMLFElement(Attributes attr) { super(attr); String eqn = attr.getValue("eqn"); StringTokenizer tok = new StringTokenizer(eqn, " "); int len = tok.countTokens(); command = tok.nextToken(); args = new Object[len - 1]; for (int i = 1; i < len; i++) { String t = tok.nextToken(); char c = t.charAt(0); if (c == '@' || c == '#') { int v = Integer.parseInt(t.substring(1)); args[i - 1] = new VMLCallout(t.charAt(0), v); } else if ('0' <= c && c <= '9') { int v = Integer.parseInt(t); args[i - 1] = new Integer(v); } else if ('a' <= c && c <= 'z') { args[i - 1] = t; } else { throw new RuntimeException("Unknown stuff: " + t); } } } private static int resolve(VMLEnv env, Object arg) { if (arg instanceof Integer) return ((Integer) arg).intValue(); if (arg instanceof VMLCallout) return env.resolveCallout((VMLCallout) arg); if (arg instanceof String) return env.resolveEnv((String) arg); throw new RuntimeException("Unknown stuff: " + arg); } public int eval(VMLEnv env) { if (command.equals("val")) { return resolve(env, args[0]); } else if (command.equals("sum")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return v + p1 - p2; } else if (command.equals("prod")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return (int) Math.round(v * p1 / (double) p2); } else if (command.equals("mid")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return (v + p1) / 2; } else if (command.equals("abs")) { int v = resolve(env, args[0]); return v > 0 ? v : -v; } else if (command.equals("min")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return v > p1 ? p1 : v; } else if (command.equals("max")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return v > p1 ? v : p1; } else if (command.equals("if")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return v > 0 ? p1 : p2; } else if (command.equals("mod")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return (int) Math.floor(Math.sqrt(v * (double) v + p1 * (double) p1 + p2 * (double) p2)); } else if (command.equals("atan2")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return (int) Math.floor(0x10000 * Math.toDegrees(Math.atan2(p1, v))); } else if (command.equals("sin")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return (int) Math.floor(v * Math.sin(Math.toRadians(p1 / (double) 0x10000))); } else if (command.equals("cos")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return (int) Math.floor(v * Math.cos(Math.toRadians(p1 / (double) 0x10000))); } else if (command.equals("cosatan2")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return (int) Math.floor(v * Math.cos(Math.atan2(p2, p1))); } else if (command.equals("sinatan2")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return (int) Math.floor(v * Math.sin(Math.atan2(p2, p1))); } else if (command.equals("sqrt")) { int v = resolve(env, args[0]); return (int) Math.floor(Math.sqrt(v)); } else if (command.equals("sumangle")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); return v + p1 * 0x10000 - p2 * 0x10000; } else if (command.equals("ellipse")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); int p2 = resolve(env, args[2]); double r = v / (double) p1; return (int) Math.floor(p2 * Math.sqrt(1 - r * r)); } else if (command.equals("tan")) { int v = resolve(env, args[0]); int p1 = resolve(env, args[1]); return (int) Math.floor(v * Math.tan(Math.toRadians(p1 / (double) 0x10000))); } else { throw new RuntimeException("unknown command: " + command); } } }