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