001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit https://imagingbook.com for additional details. 008 ******************************************************************************/ 009package imagingbook.common.ij.overlay; 010 011import imagingbook.common.math.Matrix; 012 013import java.awt.BasicStroke; 014import java.awt.Color; 015 016/** 017 * This is basically a mirror class of {@link BasicStroke} adding line and fill colors. Instances of this class are 018 * cloneable and mutable, setters for all fields are provided, i.e., strokes can be easily customized. Use 019 * {@link #getBasicStroke()} to convert to an AWT {@link BasicStroke} instance. 020 * 021 * @author WB 022 * @version 2021/10/26 023 */ 024public class ColoredStroke implements Cloneable { // TODO: simplify API 025 026 public static final Color DefaultStrokeColor = Color.black; 027 public static final Color DefaultFillColor = null; 028 029 private float lineWidth; 030 private int endCap; 031 private int lineJoin; 032 private float miterLimit; 033 private float[] dashArray; 034 private float dashPhase; 035 private Color strokeColor; 036 private Color fillColor; 037 038 public ColoredStroke() { 039 this(new BasicStroke()); 040 } 041 042 public ColoredStroke(BasicStroke bs) { 043 this( 044 bs.getLineWidth(), 045 bs.getEndCap(), 046 bs.getLineJoin(), 047 bs.getMiterLimit(), 048 bs.getDashArray(), 049 bs.getDashPhase(), 050 DefaultStrokeColor, 051 DefaultFillColor); 052 } 053 054 public ColoredStroke(double lineWidth, int endCap, int lineJoin, 055 double miterLimit, float[] dashArray, double dashPhase, 056 Color strokeColor, Color fillColor) { 057 this.lineWidth = (float) lineWidth; 058 this.endCap = endCap; 059 this.lineJoin = lineJoin; 060 this.miterLimit = (float) miterLimit; 061 this.dashArray = dashArray; 062 this.dashPhase = (float) dashPhase; 063 this.strokeColor = strokeColor; 064 this.fillColor = fillColor; 065 } 066 067 // convenience constructors 068 069 public ColoredStroke(double lineWidth, Color strokeColor, double dashLength) { 070 this(); 071 this.setLineWidth(lineWidth); 072 this.setStrokeColor(strokeColor); 073 if (dashLength > 0) { 074 this.setDash(dashLength); 075 } 076 } 077 078 public ColoredStroke(double lineWidth, Color strokeColor) { 079 this(); 080 this.setLineWidth(lineWidth); 081 this.setStrokeColor(strokeColor); 082 } 083 084 public ColoredStroke(double lineWidth, Color strokeColor, Color fillColor) { 085 this(); 086 this.setLineWidth(lineWidth); 087 this.setStrokeColor(strokeColor); 088 this.setFillColor(fillColor); 089 } 090 091 @Override 092 public ColoredStroke clone() { 093 return new ColoredStroke(lineWidth, endCap, lineJoin, 094 miterLimit, dashArray, dashPhase, strokeColor, fillColor); 095 } 096 097 // ------------------------------------------------------- 098 099 public void setLineWidth(double lineWidth) { 100 this.lineWidth = (float) lineWidth; 101 } 102 103 public void setEndCap(int endCap) { 104 this.endCap = endCap; 105 } 106 107 public void setLineJoin(int lineJoin) { 108 this.lineJoin = lineJoin; 109 } 110 111 public void setMiterLimit(double miterLimit) { 112 this.miterLimit = (float) miterLimit; 113 } 114 115 public void setDashArray(float[] dashArray) { 116 this.dashArray = dashArray; 117 } 118 119 public void setDashPhase(double dashPhase) { 120 this.dashPhase = (float) dashPhase; 121 } 122 123 public void setStrokeColor(Color strokeColor) { 124 this.strokeColor = strokeColor; 125 } 126 127 public void setFillColor(Color fillColor) { 128 this.fillColor = fillColor; 129 } 130 131 // ------------------------------------------------------------- 132 133 /** 134 * Convenience method to set (unset) the dash pattern Usage examples: 135 * <pre> 136 * setDash(6); // = setDashArray(new float[] {6}) 137 * setDash(6, 4); // = setDashArray(new float[] {6, 4}) 138 * setDash(); // = setDashArray(null) 139 * </pre> 140 * 141 * @param dashes a (possibly empty) sequence of dash lengths 142 * @see BasicStroke 143 * @see BasicStroke#getDashArray() 144 */ 145 public void setDash(double... dashes) { 146 if (dashes == null || dashes.length == 0) { 147 this.dashArray = null; 148 } 149 else { 150 this.dashArray = Matrix.toFloat(dashes); 151 } 152 } 153 154 // ------------------------------------------------------------- 155 156 public Color getStrokeColor() { 157 return this.strokeColor; 158 } 159 160 public Color getFillColor() { 161 return this.fillColor; 162 } 163 164 // ------------------------------------------------------------- 165 166 /** 167 * Returns a AWT {@link BasicStroke} instance for the current state of this stroke (with no color information). 168 * 169 * @return a AWT {@link BasicStroke} 170 */ 171 public BasicStroke getBasicStroke() { // TODO: invoke once or only when parameters change? 172 return new BasicStroke(lineWidth, endCap, lineJoin, 173 miterLimit, dashArray, dashPhase); 174 } 175 176}