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