/* * @(#)CharcoalStroke.java * * $Date: 2014-06-06 20:04:49 +0200 (P, 06 jún. 2014) $ * * Copyright (c) 2011 by Jeremy Wood. * All rights reserved. * * The copyright of this software is owned by Jeremy Wood. * You may not use, copy or modify this software, except in * accordance with the license agreement you entered into with * Jeremy Wood. For details see accompanying license terms. * * This software is probably, but not necessarily, discussed here: * https://javagraphics.java.net/ * * That site should also contain the most recent official version * of this software. (See the SVN repository for more details.) */ package com.bric.awt; import com.bric.geom.GeneralPathWriter; import java.awt.BasicStroke; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.GeneralPath; /** * This applies the {@link CharcoalEffect} to another <code>Stroke</code>. * <p> * By default this is built on top of a <code>BasicStroke</code>, but you can * use any other relatively simple stroke. The nature of the charcoal effect * requires continuous areas of at least 2 pixels to really be visible. * <P> It is not recommended to layer a <code>CharcoalStroke</code> on top * of another <code>CharcoalStroke</code>, because they are very * complex. */ public class CharcoalStroke implements FilteredStroke { Stroke stroke; float crackSize, angle; int randomSeed; /** * Create a new <code>CharcoalStroke</code> built on top of * a <code>BasicStroke</code>. * * @param width the width of the <code>BasicStroke</code>. * @param crackSize a value from 0-1 indicating how deep the crack should be. * @param angle the angle, in radians. */ public CharcoalStroke(float width, float crackSize, float angle) { this(new BasicStroke(width), crackSize, angle, 0); } /** * Create a new <code>CharcoalStroke</code> built on top of * another <code>Stroke</code>. * * @param s the stroke to apply the charcoal effect to. * @param crackSize a value from 0-1 indicating how deep the crack should be. * @param angle the angle, in radians. * @param randomSeed the random seed to use. */ public CharcoalStroke(Stroke s, float crackSize, float angle, int randomSeed) { this.stroke = s; this.crackSize = crackSize; this.angle = angle; this.randomSeed = randomSeed; } /** * @return the random seed this object uses. */ public int getRandomSeed() { return randomSeed; } /** * @return the angle (in radians) this effect uses. */ public float getAngle() { return angle; } /** * This creates a <code>CharcoalStroke</code> on top of a * simple <code>BasicStroke</code>, with a fixed angle of 45 degrees. * * @param width the width of the <code>BasicStroke</code> * @param crackSize a value from 0-1 indicating how deep the crack should be. */ public CharcoalStroke(float width, float crackSize) { this(new BasicStroke(width), crackSize, (float) (Math.PI / 4), 0); } /** * Creates a similar stroke where only the crack depth (0-1) is * redefined. * * @param cracks the new crack depth. * @return a new stroke. */ public CharcoalStroke deriveStroke(float cracks) { return new CharcoalStroke(stroke, cracks, angle, randomSeed); } /** * Creates a similar stroke where the underlying stroke is * redefined. * * @param newStroke the new underlying Stroke. This could be * a <code>BasicShape</code>, or your own stroke. It is not * recommended to layer a <code>CharcoalStroke</code> on top * of another <code>CharcoalStroke</code>, because they are very * complex. */ public FilteredStroke deriveStroke(Stroke newStroke) { return new CharcoalStroke(newStroke, crackSize, angle, randomSeed); } public Shape createStrokedShape(Shape p) { Shape shape = stroke.createStrokedShape(p); if (crackSize == 0) { return shape; } GeneralPath newShape = new GeneralPath(shape.getPathIterator(null).getWindingRule()); GeneralPathWriter writer = new GeneralPathWriter(newShape); float maxDepth = Float.MAX_VALUE; if (stroke instanceof BasicStroke) { maxDepth = ((BasicStroke) stroke).getLineWidth() * 2; } CharcoalEffect charcoal = new CharcoalEffect(writer, crackSize, angle, randomSeed, maxDepth); charcoal.write(shape); return (newShape); } /** * Returns the underlying stroke this <code>CharcoalStroke</code> is layered * on top of. */ public Stroke getStroke() { return stroke; } /** * Returns the crack size. This is a float from 0 to 1 indicating how * deep the cracks in this effect run. * * @return the crack size, as a float from [0, 1]. */ public float getCrackSize() { return crackSize; } }