Add a way to precise mark border color for scatter plots
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / mark / MarkSpriteFactory.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  */
11
12 package org.scilab.modules.renderer.JoGLView.mark;
13
14 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
15 import org.scilab.forge.scirenderer.shapes.appearance.Color;
16 import org.scilab.forge.scirenderer.texture.Texture;
17 import org.scilab.forge.scirenderer.texture.TextureDrawer;
18 import org.scilab.forge.scirenderer.texture.TextureDrawingTools;
19 import org.scilab.forge.scirenderer.texture.TextureManager;
20 import org.scilab.modules.graphic_objects.contouredObject.Mark;
21 import org.scilab.modules.graphic_objects.figure.ColorMap;
22 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
23
24 import java.awt.Dimension;
25
26 /**
27  * @author Pierre Lando
28  */
29 public class MarkSpriteFactory {
30
31     /**
32      * Return a mark sprite corresponding to the given scilab mark.
33      *
34      *
35      * @param spriteManager the current sprite manager.
36      * @param mark the scilab mark.
37      * @param colorMap the scilab color map.
38      * @return a mark sprite corresponding to the given scilab mark.
39      */
40     public static Texture getMarkSprite(TextureManager spriteManager, Mark mark, Integer selectedColor, ColorMap colorMap, Appearance appearance) {
41         int finalSize;
42
43         /**
44          * Compute the sprite pixel size.
45          */
46         if (mark.getMarkSizeUnit() == Mark.MarkSizeUnitType.TABULATED) {
47             // Special case for compatibility with older versions
48             // dot mark with tabulated size of 0 is a single pixel
49             // drawn in pixel size instead of tabulated size
50             if (mark.getStyle() == 0 && mark.getSize() == 0) {
51                 finalSize = 1;
52             } else {
53                 finalSize = (8 + 2 * mark.getSize());
54             }
55         } else {
56             finalSize = mark.getSize();
57         }
58
59         Texture sprite = spriteManager.createTexture();
60         sprite.setDrawer(getSpriteDrawer(mark, selectedColor, finalSize, colorMap, appearance));
61
62         return sprite;
63     }
64
65     /**
66      * Return the sprite drawer corresponding to the given mark.
67      * @param mark the mark to draw.
68      * @param finalSize the final mark size.
69      * @param colorMap the scilab colormap to use.
70      * @return the sprite drawer corresponding to the given mark.
71      */
72     private static TextureDrawer getSpriteDrawer(Mark mark, Integer selectedColor, int finalSize, ColorMap colorMap, Appearance usedAppearance) {
73         final Appearance appearance = new Appearance();
74         Integer markColor = selectedColor == null ? mark.getForeground() : selectedColor;
75         Color backgroundColor;
76         Color foregroundColor;
77
78         if (colorMap != null) {
79             backgroundColor = ColorFactory.createColor(colorMap, mark.getBackground());
80             foregroundColor = ColorFactory.createColor(colorMap, markColor);
81         } else if (mark.getBackground() == -3 && mark.getForeground() == -3) {
82             backgroundColor = new Color(0f, 0f, 0f, 1f);
83             foregroundColor = new Color(0f, 0f, 0f, 1f);
84         } else if (mark.getBackground() == -3) {
85             backgroundColor = new Color(0f, 0f, 0f, 1f);
86             foregroundColor = new Color(1f, 1f, 1f, 1f);
87         } else {
88             backgroundColor = new Color(1f, 1f, 1f, 1f);
89             foregroundColor = new Color(0f, 0f, 0f, 1f);
90         }
91
92         if (mark.getBackground() != 0) {
93             appearance.setFillColor(backgroundColor);
94         } else {
95             appearance.setFillColor(new Color(0.0f, 0.0f, 0.0f, 0.0f));
96         }
97         appearance.setLineColor(foregroundColor);
98         if (usedAppearance != null) {
99             appearance.setLineWidth(usedAppearance.getLineWidth());
100         }
101
102         if (finalSize == 0) {
103             // when finalSize is 0 then a dot is drawn so we draw a dot with a PlusSpriteDrawer
104             // which is well exported with size equal to 1 (see bug 13551)
105             finalSize = 1;
106         }
107
108         if (finalSize != 1) {
109             switch (mark.getStyle()) {
110                 case  0:
111                     if (colorMap == null) {
112                         return new DotSpriteDrawer(backgroundColor, finalSize);
113                     } else {
114                         return new DotSpriteDrawer(foregroundColor, finalSize);
115                     }
116                 case  1:
117                     return new PlusSpriteDrawer(appearance, finalSize);
118                 case  2:
119                     return new CrossSpriteDrawer(appearance, finalSize);
120                 case  3:
121                     return new StarSpriteDrawer(appearance, finalSize);
122                 case  4:
123                     if (colorMap == null) {
124                         return new FilledDiamondSpriteDrawer(backgroundColor, finalSize);
125                     } else {
126                         return new FilledDiamondSpriteDrawer(foregroundColor, finalSize);
127                     }
128                 case  5:
129                     return new DiamondSpriteDrawer(appearance, finalSize);
130                 case  6:
131                     return new TriangleUpSpriteDrawer(appearance, finalSize);
132                 case  7:
133                     return new TriangleDownSpriteDrawer(appearance, finalSize);
134                 case  8:
135                     return new DiamondPlusSpriteDrawer(appearance, finalSize);
136                 case  9:
137                     return new CircleSpriteDrawer(appearance, finalSize);
138                 case 10:
139                     return new AsteriskSpriteDrawer(appearance, finalSize);
140                 case 11:
141                     return new SquareSpriteDrawer(appearance, finalSize);
142                 case 12:
143                     return new TriangleRightSpriteDrawer(appearance, finalSize);
144                 case 13:
145                     return new TriangleLeftSpriteDrawer(appearance, finalSize);
146                 case 14:
147                     return new PentagramSpriteDrawer(appearance, finalSize);
148
149                 default:
150                     return new PlusSpriteDrawer(appearance, finalSize);
151             }
152         } else {
153             return new PlusSpriteDrawer(appearance, finalSize);
154         }
155     }
156
157     /**
158      * Abstract class for all scilab mark sprites.
159      */
160     private static abstract class ScilabSpriteDrawer implements TextureDrawer {
161         protected final Appearance appearance;
162         protected final int size;
163
164         public ScilabSpriteDrawer(Appearance appearance, int size) {
165             this.appearance = appearance;
166             this.size = size;
167         }
168
169         @Override
170         public OriginPosition getOriginPosition() {
171             return TextureDrawer.OriginPosition.CENTER;
172         }
173
174         @Override
175         public Dimension getTextureSize() {
176
177             /** Add a margin such that (0, 0) was pixel aligned. */
178             int margin;
179             if (size % 2 == 0) {
180                 margin = 3;
181             } else {
182                 margin = 2;
183             }
184             return new Dimension(size + margin, size + margin);
185         }
186     }
187
188     /**
189      * Dot sprite
190      * Scilab ID = 0
191      */
192     private static class DotSpriteDrawer extends ScilabSpriteDrawer {
193         private final Color color;
194
195         public DotSpriteDrawer(Color color, int size) {
196             super(null, size);
197             this.color = color;
198         }
199
200         @Override
201         public void draw(TextureDrawingTools textureDrawingTools) {
202             textureDrawingTools.fillDisc(0, 0, size, color);
203         }
204     }
205
206     /**
207      * Plus sprite
208      * Scilab ID = 1
209      */
210     private static class PlusSpriteDrawer extends ScilabSpriteDrawer {
211
212         public PlusSpriteDrawer(Appearance appearance, int size) {
213             super(appearance, size);
214         }
215
216         @Override
217         public void draw(TextureDrawingTools textureDrawingTools) {
218             textureDrawingTools.drawPlus(size, appearance);
219         }
220     }
221
222     /**
223      * Cross sprite
224      * Scilab ID = 2
225      */
226     private static class CrossSpriteDrawer extends ScilabSpriteDrawer {
227         private final int[] coordinate1;
228         private final int[] coordinate2;
229
230         public CrossSpriteDrawer(Appearance appearance, int size) {
231             super(appearance, size);
232             int r = (int) (size * Math.sqrt(2.0) / 2.0);
233             coordinate1 = new int[] { -r, -r, r,  r};
234             coordinate2 = new int[] { -r,  r, r, -r};
235         }
236
237         @Override
238         public void draw(TextureDrawingTools textureDrawingTools) {
239             textureDrawingTools.drawPolyline(coordinate1, appearance);
240             textureDrawingTools.drawPolyline(coordinate2, appearance);
241         }
242     }
243
244     /**
245      * Star sprite
246      * Scilab ID = 3
247      */
248     private static class StarSpriteDrawer extends ScilabSpriteDrawer {
249         private final int[] coordinate1;
250         private final int[] coordinate2;
251
252         public StarSpriteDrawer(Appearance appearance, int size) {
253             super(appearance, size);
254             int r = size / 2;
255             coordinate1 = new int[] { -r, 0, r, 0};
256             coordinate2 = new int[] { 0, -r, 0, r};
257         }
258
259         @Override
260         public void draw(TextureDrawingTools textureDrawingTools) {
261             textureDrawingTools.fillDisc(0, 0, size, appearance.getFillColor());
262             textureDrawingTools.drawCircle(0, 0, size, appearance);
263             textureDrawingTools.drawPolyline(coordinate1, appearance);
264             textureDrawingTools.drawPolyline(coordinate2, appearance);
265         }
266     }
267
268     /**
269      * Filled diamond sprite
270      * Scilab ID = 4
271      */
272     private static class FilledDiamondSpriteDrawer extends ScilabSpriteDrawer {
273         private final Appearance appearance;
274         private final int[] coordinates;
275
276         public FilledDiamondSpriteDrawer(Color color, int size) {
277             super(null, size);
278             int r = size / 2;
279
280             appearance = new Appearance();
281             appearance.setFillColor(color);
282             appearance.setLineColor(color);
283
284             coordinates = new int[] { -r, 0, 0, -r, +r, 0, 0, +r};
285         }
286
287         @Override
288         public void draw(TextureDrawingTools textureDrawingTools) {
289             textureDrawingTools.fillPolygon(coordinates, appearance);
290         }
291     }
292
293     /**
294      * Abstract class for all the triangle mark sprites.
295      */
296     private static abstract class TriangleSpriteDrawer extends ScilabSpriteDrawer {
297         protected final int r;
298         protected final int basex;
299         protected final int basey;
300         protected int[] coordinates;
301
302         public TriangleSpriteDrawer(Appearance appearance, int size) {
303             super(appearance, size);
304             double tmpr = (double)(size / 2);
305
306             r = (int) (tmpr);
307
308             basex = (int) (tmpr * 0.5 * Math.sqrt(3));
309             basey = (int) (tmpr * 0.5);
310         }
311
312         @Override
313         public void draw(TextureDrawingTools textureDrawingTools) {
314             textureDrawingTools.fillPolygon(coordinates, appearance);
315         }
316     }
317
318     /**
319      * Diamond sprite
320      * Scilab ID = 5
321      */
322     private static class DiamondSpriteDrawer extends ScilabSpriteDrawer {
323         protected final int[] coordinates;
324
325         public DiamondSpriteDrawer(Appearance appearance, int size) {
326             super(appearance, size);
327             int r = size / 2;
328
329             coordinates = new int[] { -r, 0, 0, -r, r, 0, 0, r};
330         }
331
332         @Override
333         public void draw(TextureDrawingTools textureDrawingTools) {
334             textureDrawingTools.fillPolygon(coordinates, appearance);
335         }
336     }
337
338     /**
339      * Triangle up sprite
340      * Scilab ID = 6
341      */
342     private static class TriangleUpSpriteDrawer extends TriangleSpriteDrawer {
343         public TriangleUpSpriteDrawer(Appearance appearance, int size) {
344             super(appearance, size);
345
346             coordinates = new int[] { -basex, basey, 0, -r, basex, basey};
347         }
348     }
349
350     /**
351      * Triangle down sprite
352      * Scilab ID = 7
353      */
354     private static class TriangleDownSpriteDrawer extends TriangleSpriteDrawer {
355         public TriangleDownSpriteDrawer(Appearance appearance, int size) {
356             super(appearance, size);
357
358             coordinates = new int[] { -basex, -basey, basex, -basey, 0, r};
359         }
360     }
361
362     /**
363      * Diamond plus sprite
364      * Scilab ID = 8
365      */
366     private static class DiamondPlusSpriteDrawer extends DiamondSpriteDrawer {
367         private final int[] coordinate1;
368         private final int[] coordinate2;
369
370         public DiamondPlusSpriteDrawer(Appearance appearance, int size) {
371             super(appearance, size);
372             coordinate1 = new int[] {coordinates[0], coordinates[1], coordinates[4], coordinates[5]};
373             coordinate2 = new int[] {coordinates[2], coordinates[3], coordinates[6], coordinates[7]};
374         }
375
376         @Override
377         public void draw(TextureDrawingTools textureDrawingTools) {
378             super.draw(textureDrawingTools);
379             textureDrawingTools.drawPolyline(coordinate1, appearance);
380             textureDrawingTools.drawPolyline(coordinate2, appearance);
381         }
382     }
383
384     /**
385      * Circle sprite
386      * Scilab ID = 9
387      */
388     private static class CircleSpriteDrawer extends ScilabSpriteDrawer {
389
390         public CircleSpriteDrawer(Appearance appearance, int size) {
391             super(appearance, size);
392         }
393
394         @Override
395         public void draw(TextureDrawingTools textureDrawingTools) {
396             textureDrawingTools.fillDisc(0, 0, size, appearance.getFillColor());
397             textureDrawingTools.drawCircle(0, 0, size, appearance);
398         }
399     }
400
401     /**
402      * Asterisk sprite
403      * Scilab ID = 10
404      */
405     private static class AsteriskSpriteDrawer extends ScilabSpriteDrawer {
406         private final int[] coordinate1;
407         private final int[] coordinate2;
408         private final int[] coordinate3;
409         private final int[] coordinate4;
410
411         public AsteriskSpriteDrawer(Appearance appearance, int size) {
412             super(appearance, size);
413             int r = size / 2;
414             coordinate1 = new int[] { -r, 0, r, 0};
415             coordinate2 = new int[] { 0, -r, 0, r};
416             r = (int) (r * Math.sqrt(2.0) / 2.0);
417             coordinate3 = new int[] { -r, -r, r, r};
418             coordinate4 = new int[] { -r, r, +r, -r};
419         }
420
421         @Override
422         public void draw(TextureDrawingTools textureDrawingTools) {
423             textureDrawingTools.drawPolyline(coordinate1, appearance);
424             textureDrawingTools.drawPolyline(coordinate2, appearance);
425             textureDrawingTools.drawPolyline(coordinate3, appearance);
426             textureDrawingTools.drawPolyline(coordinate4, appearance);
427         }
428     }
429
430     /**
431      * Square sprite
432      * Scilab ID = 11
433      */
434     private static class SquareSpriteDrawer extends ScilabSpriteDrawer {
435         private final int[] coordinate;
436
437         public SquareSpriteDrawer(Appearance appearance, int size) {
438             super(appearance, size);
439             int r = size / 2;
440             coordinate = new int[] { -r, -r, +r, -r, +r, +r, -r, +r};
441         }
442
443         @Override
444         public void draw(TextureDrawingTools textureDrawingTools) {
445             textureDrawingTools.fillPolygon(coordinate, appearance);
446         }
447     }
448
449     /**
450      * Triangle right sprite
451      * Scilab ID = 12
452      */
453     private static class TriangleRightSpriteDrawer extends TriangleSpriteDrawer {
454         public TriangleRightSpriteDrawer(Appearance appearance, int size) {
455             super(appearance, size);
456
457             coordinates = new int[] { -basey, basex, -basey, -basex, r, 0};
458         }
459     }
460
461     /**
462      * Triangle left sprite
463      * Scilab ID = 13
464      */
465     private static class TriangleLeftSpriteDrawer extends TriangleSpriteDrawer {
466         public TriangleLeftSpriteDrawer(Appearance appearance, int size) {
467             super(appearance, size);
468
469             coordinates = new int[] {basey, basex, -r, 0, basey, -basex};
470         }
471     }
472
473     /**
474      * Pentagram sprite (five-pointed star)
475      * Scilab ID = 14
476      */
477     private static class PentagramSpriteDrawer extends ScilabSpriteDrawer {
478         private final int[] coordinates;
479
480         private static final double COS_PI_OVER_10 = Math.cos(Math.PI / 10.0);
481         private static final double SIN_PI_OVER_10 = Math.sin(Math.PI / 10.0);
482         private static final double COS_3_PI_OVER_10 = Math.cos(3.0 * Math.PI / 10.0);
483         private static final double SIN_3_PI_OVER_10 = Math.sin(3.0 * Math.PI / 10.0);
484
485         public PentagramSpriteDrawer(Appearance appearance, int size) {
486             super(appearance, size);
487
488             int r = size / 2;
489
490             double tmpy = SIN_PI_OVER_10 * (double)r;
491
492             int x = (int)(COS_PI_OVER_10 * (double)r);
493             int y = (int)(SIN_PI_OVER_10 * (double)r);
494
495             int x2 = (int)(COS_3_PI_OVER_10 * (double)r);
496             int y2 = (int)(SIN_3_PI_OVER_10 * (double)r);
497
498             double tmpinnr = tmpy / SIN_3_PI_OVER_10;
499
500
501             int xinn = (int)(tmpinnr * COS_3_PI_OVER_10);
502             int yinn = y;
503
504             int xinn2 = (int)(tmpinnr * COS_PI_OVER_10);
505             int yinn2 = (int)(tmpinnr * SIN_PI_OVER_10);
506
507             int innr = (int)tmpinnr;
508
509             coordinates = new int[] { -x2, y2, -xinn2, yinn2, -x, -y, -xinn, -yinn, 0, -r, xinn, -yinn, x, -y, xinn2, yinn2, x2, y2, 0, innr};
510         }
511
512         @Override
513         public void draw(TextureDrawingTools textureDrawingTools) {
514             textureDrawingTools.fillPolygon(coordinates, appearance);
515         }
516     }
517 }