]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.g2d/src/org/simantics/g2d/svg/StrokeDesc.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / svg / StrokeDesc.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g2d.svg;
13
14 import java.awt.BasicStroke;
15 import java.awt.Graphics2D;
16
17 //import org.apache.batik.util.CSSConstants;
18
19 /**
20  * @author Tuukka Lehtonen
21  */
22 public class StrokeDesc {
23
24     public static final String DEFAULT_MEASUREMENT_UNIT    = "";
25
26     /**
27      * This empty array stands for no dashing.
28      */
29     public static final double[] NO_DASHES_DASH_ARRAY = {};
30     
31 //    public static final String[] joinConv             = { "miter", "round", "bevel" };
32 //    public static final String[] capConv              = { "butt", "round", "square" };
33     
34     /**
35      * Joins path segments by extending their outside edges until they meet.
36      */
37     public final static Integer JOIN_MITER = BasicStroke.JOIN_MITER;
38
39     /**
40      * Joins path segments by rounding off the corner at a radius of half the
41      * line width.
42      */
43     public final static Integer JOIN_ROUND = BasicStroke.JOIN_ROUND;
44
45     /**
46      * Joins path segments by connecting the outer corners of their wide
47      * outlines with a straight segment.
48      */
49     public final static Integer JOIN_BEVEL = BasicStroke.JOIN_BEVEL;
50
51     /**
52      * Ends unclosed subpaths and dash segments with no added decoration.
53      */
54     public final static Integer CAP_BUTT   = BasicStroke.CAP_BUTT;
55
56     /**
57      * Ends unclosed subpaths and dash segments with a round decoration that has
58      * a radius equal to half of the width of the pen.
59      */
60     public final static Integer CAP_ROUND  = BasicStroke.CAP_ROUND;
61
62     /**
63      * Ends unclosed subpaths and dash segments with a square projection that
64      * extends beyond the end of the segment to a distance equal to half of the
65      * line width.
66      */
67     public final static Integer CAP_SQUARE = BasicStroke.CAP_SQUARE;
68
69     
70     private String               paint;
71
72     private double               opacity;
73
74     private double               width;
75
76     private LineJoin         join;
77
78     private LineCap          cap;
79
80     private double               miterLimit;
81
82     /**
83      * An empty array (length == 0) stands for no dashing.
84      */
85     private double[]             dash;
86
87     private double               dashOffset;
88     
89     /**
90      * One of valid measurement units in SVG, such as "in", "mm", "cm", etc.
91      */
92     private String               unitSuffix;
93
94     public StrokeDesc() {
95         this(StyleConstants.INHERIT, 1.0, 1.0, LineJoin.bevel, LineCap.butt, 10.0, null, 0.0);
96     }
97     
98     public StrokeDesc(String paint) {
99         this(paint, 1.0, 1.0, LineJoin.bevel, LineCap.butt, 10.0, null, 0.0);
100     }
101     
102     public StrokeDesc(String paint, double opacity, double width) {
103         this(paint, opacity, width, LineJoin.bevel, LineCap.butt, 10.0, null, 0.0);
104     }
105
106     public StrokeDesc(String paint, double opacity, double width, LineJoin join, LineCap cap) {
107         this(paint, opacity, width, join, cap, 10.0, null, 0.0);
108     }
109     
110     public StrokeDesc(String paint, double opacity, double width, LineJoin join, LineCap cap, double miterLimit, double[] dashArray, double dashOffset) {
111         setPaint(paint);
112         setOpacity(opacity);
113         setLineWidth(width);
114         setLineJoin(join);
115         setEndCap(cap);
116         setMiterLimit(miterLimit);
117         
118         if (dashArray == null || dashArray.length == 0)
119             dashArray = NO_DASHES_DASH_ARRAY;
120         this.dash = dashArray;
121         this.dashOffset = dashOffset;
122         
123         this.unitSuffix = DEFAULT_MEASUREMENT_UNIT;
124     }
125     
126     public void setUnitSuffix(String unitSuffix) {
127         if (!SVGUnits.isValidUnit(unitSuffix))
128             throw new IllegalArgumentException("invalid unit suffix: " + unitSuffix);
129         this.unitSuffix = unitSuffix;
130     }
131     
132     public String getUnitSuffix() {
133         return unitSuffix;
134     }
135     
136     public String getPaint() {
137         return paint;
138     }
139     
140     public void setPaint(String paint) {
141         this.paint = paint;
142     }
143     
144     public double getOpacity() {
145         return opacity;
146     }
147     
148     public void setOpacity(double opacity) {
149         this.opacity = opacity;
150     }
151     
152     /**
153      * Returns the line width. Line width is represented in user space, which is
154      * the default-coordinate system used by Java 2D. See the
155      * <code>Graphics2D</code> class comments for more information on the user
156      * space coordinate system.
157      * 
158      * @return the line width of this <code>BasicStroke</code>.
159      * @see Graphics2D
160      */
161     public double getLineWidth() {
162         return width;
163     }
164     
165     public String getLineWidthWithUnit() {
166         return String.valueOf(width) + unitSuffix;
167     }
168
169     public void setLineWidth(double width) {
170         this.width = width;
171     }
172     
173     /**
174      * Returns the end cap style.
175      * 
176      * @return the end cap style of this <code>BasicStroke</code> as one of
177      *         the static <code>int</code> values that define possible end cap
178      *         styles.
179      */
180     public LineCap getEndCap() {
181         return cap;
182     }
183
184     public void setEndCap(LineCap cap) {
185         this.cap = cap;
186     }
187     
188     /**
189      * Returns the line join style.
190      * 
191      * @return the line join style of the <code>BasicStroke</code> as one of
192      *         the static <code>int</code> values that define possible line
193      *         join styles.
194      */
195     public LineJoin getLineJoin() {
196         return join;
197     }
198
199     public void setLineJoin(LineJoin join) {
200         this.join = join;
201     }
202     
203     /**
204      * Returns the limit of miter joins.
205      * 
206      * @return the limit of miter joins of the <code>BasicStroke</code>.
207      */
208     public double getMiterLimit() {
209         return miterLimit;
210     }
211
212     public void setMiterLimit(double miterLimit) {
213         this.miterLimit = miterLimit;
214     }
215     
216     /**
217      * Returns the array representing the lengths of the dash segments.
218      * Alternate entries in the array represent the user space lengths of the
219      * opaque and transparent segments of the dashes. As the pen moves along the
220      * outline of the <code>Shape</code> to be stroked, the user space
221      * distance that the pen travels is accumulated. The distance value is used
222      * to index into the dash array. The pen is opaque when its current
223      * cumulative distance maps to an even element of the dash array and
224      * transparent otherwise.
225      * 
226      * @return the dash array.
227      */
228     public double[] getDashArray() {
229         if (dash == NO_DASHES_DASH_ARRAY)
230             return dash;
231         return (double[]) dash.clone();
232     }
233
234     public void setDashArray(double[] dash) {
235         if (dash == null || dash.length == 0)
236             dash = NO_DASHES_DASH_ARRAY;
237         this.dash = dash;
238     }
239     
240     /**
241      * Returns the current dash phase. The dash phase is a distance specified in
242      * user coordinates that represents an offset into the dashing pattern. In
243      * other words, the dash phase defines the point in the dashing pattern that
244      * will correspond to the beginning of the stroke.
245      * 
246      * @return the dash phase as a <code>double</code> value.
247      */
248     public double getDashOffset() {
249         return dashOffset;
250     }
251     
252     public void setDashOffset(double dashOffset) {
253         this.dashOffset = dashOffset;
254     }
255
256     /**
257      * Returns the hashcode for this stroke.
258      * 
259      * @return a hash code for this stroke.
260      */
261     public int hashCode() {
262         int hash = (int) Double.doubleToLongBits(width);
263         hash = hash * 31 + join.ordinal();
264         hash = hash * 31 + cap.ordinal();
265         hash = hash * 31 + (int) Double.doubleToLongBits(miterLimit);
266         if (dash != null) {
267             hash = hash * 31 + (int) Double.doubleToLongBits(dashOffset);
268             for (int i = 0; i < dash.length; i++) {
269                 hash = hash * 31 + (int) Double.doubleToLongBits(dash[i]);
270             }
271         }
272         return hash;
273     }
274
275     /**
276      * Returns true if this BasicStroke represents the same stroking operation
277      * as the given argument.
278      * 
279      * <p>
280      * Tests if a specified object is equal to this <code>Stroke</code> by
281      * first testing if it is a <code>BasicStroke</code> and then comparing
282      * its width, join, cap, miter limit, dash, and dash phase attributes with
283      * those of this <code>Stroke</code>.
284      * 
285      * @param obj the specified object to compare to this <code>Stroke</code>
286      * @return <code>true</code> if the width, join, cap, miter limit, dash,
287      *         and dash phase are the same for both objects; <code>false</code>
288      *         otherwise.
289      */
290     public boolean equals(Object obj) {
291         if (!(obj instanceof StrokeDesc)) {
292             return false;
293         }
294
295         StrokeDesc bs = (StrokeDesc) obj;
296         if (width != bs.width) {
297             return false;
298         }
299
300         if (join != bs.join) {
301             return false;
302         }
303
304         if (cap != bs.cap) {
305             return false;
306         }
307
308         if (miterLimit != bs.miterLimit) {
309             return false;
310         }
311
312         if (dash != null) {
313             if (dashOffset != bs.dashOffset) {
314                 return false;
315             }
316
317             if (!java.util.Arrays.equals(dash, bs.dash)) {
318                 return false;
319             }
320         } else if (bs.dash != null) {
321             return false;
322         }
323
324         return true;
325     }
326
327 //    public String toStyleString() {
328 //        StringBuilder s = new StringBuilder();
329 //        
330 //        s.append(CSSConstants.CSS_STROKE_PROPERTY);
331 //        s.append(':');
332 //        s.append(paint);
333 //        if (!paint.equals(CSSConstants.CSS_NONE_VALUE)) {
334 //            s.append(';');
335 //            s.append(CSSConstants.CSS_STROKE_OPACITY_PROPERTY);
336 //            s.append(':');
337 //            s.append(opacity);
338 //            s.append(';');
339 //            s.append(CSSConstants.CSS_STROKE_WIDTH_PROPERTY);
340 //            s.append(':');
341 //            s.append(width);
342 //            s.append(unitSuffix);
343 //            if (dash.length > 0) {
344 //                s.append(';');
345 //                s.append(CSSConstants.CSS_STROKE_DASHARRAY_PROPERTY);
346 //                s.append(':');
347 //                appendDashArrayString(s);
348 //                s.append(';');
349 //                s.append(CSSConstants.CSS_STROKE_DASHOFFSET_PROPERTY);
350 //                s.append(':');
351 //                s.append(dashOffset);
352 //            }
353 //            s.append(';');
354 //            s.append(CSSConstants.CSS_STROKE_LINECAP_PROPERTY);
355 //            s.append(':');
356 //            s.append(cap.toString());
357 //            s.append(';');
358 //            s.append(CSSConstants.CSS_STROKE_LINEJOIN_PROPERTY);
359 //            s.append(':');
360 //            s.append(join.toString());
361 //            if (LineJoin.miter.equals(join)) {
362 //                s.append(';');
363 //                s.append(CSSConstants.CSS_STROKE_MITERLIMIT_PROPERTY);
364 //                s.append(':');
365 //                s.append(miterLimit);
366 //            }
367 //        }
368 //        s.append(';');
369 //        
370 //        return s.toString();
371 //    }
372
373     public void appendDashArrayString(StringBuilder s) {
374         if (dash.length > 0) {
375             s.append(dash[0]);
376             for (int i = 1; i < dash.length; ++i) {
377                 s.append(',');
378                 s.append(dash[i]);
379             }
380         }
381     }
382
383     public String dashArrayToString() {
384         String s = "";
385         if (dash.length > 0) {
386             s += dash[0];
387             for (int i = 1; i < dash.length; ++i) {
388                 s += ',' + dash[i];
389             }
390         }
391         return s;
392     }
393
394 }