Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2006 Jerry Huxtable
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
      5  * License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
     10  * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
     11  * governing permissions and limitations under the License.
     12  */
     13 
     14 package com.badlogic.gdx.tools.hiero.unicodefont.effects;
     15 
     16 import java.awt.BasicStroke;
     17 import java.awt.Color;
     18 import java.awt.Shape;
     19 import java.awt.Stroke;
     20 import java.awt.geom.FlatteningPathIterator;
     21 import java.awt.geom.GeneralPath;
     22 import java.awt.geom.PathIterator;
     23 import java.util.Iterator;
     24 import java.util.List;
     25 
     26 /** @author Jerry Huxtable
     27  * @author Nathan Sweet */
     28 public class OutlineZigzagEffect extends OutlineEffect {
     29 	float amplitude = 1;
     30 	float wavelength = 3;
     31 
     32 	public OutlineZigzagEffect () {
     33 		setStroke(new ZigzagStroke());
     34 	}
     35 
     36 	public OutlineZigzagEffect (int width, Color color) {
     37 		super(width, color);
     38 	}
     39 
     40 	public String toString () {
     41 		return "Outline (Zigzag)";
     42 	}
     43 
     44 	public List getValues () {
     45 		List values = super.getValues();
     46 		values.add(EffectUtil.floatValue("Wavelength", wavelength, 1, 100, "This setting controls the wavelength of the outline. "
     47 			+ "The smaller the value, the more segments will be used to draw the outline."));
     48 		values.add(EffectUtil.floatValue("Amplitude", amplitude, 0.5f, 50, "This setting controls the amplitude of the outline. "
     49 			+ "The bigger the value, the more the zigzags will vary."));
     50 		return values;
     51 	}
     52 
     53 	public void setValues (List values) {
     54 		super.setValues(values);
     55 		for (Iterator iter = values.iterator(); iter.hasNext();) {
     56 			Value value = (Value)iter.next();
     57 			if (value.getName().equals("Wavelength")) {
     58 				wavelength = ((Float)value.getObject()).floatValue();
     59 			} else if (value.getName().equals("Amplitude")) {
     60 				amplitude = ((Float)value.getObject()).floatValue();
     61 			}
     62 		}
     63 	}
     64 
     65 	class ZigzagStroke implements Stroke {
     66 		private static final float FLATNESS = 1;
     67 
     68 		public Shape createStrokedShape (Shape shape) {
     69 			GeneralPath result = new GeneralPath();
     70 			PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), FLATNESS);
     71 			float points[] = new float[6];
     72 			float moveX = 0, moveY = 0;
     73 			float lastX = 0, lastY = 0;
     74 			float thisX = 0, thisY = 0;
     75 			int type = 0;
     76 			float next = 0;
     77 			int phase = 0;
     78 			while (!it.isDone()) {
     79 				type = it.currentSegment(points);
     80 				switch (type) {
     81 				case PathIterator.SEG_MOVETO:
     82 					moveX = lastX = points[0];
     83 					moveY = lastY = points[1];
     84 					result.moveTo(moveX, moveY);
     85 					next = wavelength / 2;
     86 					break;
     87 
     88 				case PathIterator.SEG_CLOSE:
     89 					points[0] = moveX;
     90 					points[1] = moveY;
     91 					// Fall into....
     92 
     93 				case PathIterator.SEG_LINETO:
     94 					thisX = points[0];
     95 					thisY = points[1];
     96 					float dx = thisX - lastX;
     97 					float dy = thisY - lastY;
     98 					float distance = (float)Math.sqrt(dx * dx + dy * dy);
     99 					if (distance >= next) {
    100 						float r = 1.0f / distance;
    101 						while (distance >= next) {
    102 							float x = lastX + next * dx * r;
    103 							float y = lastY + next * dy * r;
    104 							if ((phase & 1) == 0)
    105 								result.lineTo(x + amplitude * dy * r, y - amplitude * dx * r);
    106 							else
    107 								result.lineTo(x - amplitude * dy * r, y + amplitude * dx * r);
    108 							next += wavelength;
    109 							phase++;
    110 						}
    111 					}
    112 					next -= distance;
    113 					lastX = thisX;
    114 					lastY = thisY;
    115 					if (type == PathIterator.SEG_CLOSE) result.closePath();
    116 					break;
    117 				}
    118 				it.next();
    119 			}
    120 			return new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(result);
    121 		}
    122 	}
    123 }
    124