1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
4  *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  */
14 
15 package org.scilab.modules.renderer.JoGLView.axes.ruler;
16 
17 import org.scilab.forge.scirenderer.ruler.RulerSpriteFactory;
18 import org.scilab.forge.scirenderer.texture.TextEntity;
19 import org.scilab.forge.scirenderer.texture.Texture;
20 import org.scilab.forge.scirenderer.texture.TextureDrawer;
21 import org.scilab.forge.scirenderer.texture.TextureDrawingTools;
22 import org.scilab.forge.scirenderer.texture.TextureManager;
23 import org.scilab.modules.graphic_objects.axes.Axes;
24 import org.scilab.modules.graphic_objects.axes.AxesContainer;
25 import org.scilab.modules.graphic_objects.axes.AxisProperty;
26 import org.scilab.modules.graphic_objects.figure.ColorMap;
27 import org.scilab.modules.graphic_objects.figure.Figure;
28 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
29 import org.scilab.modules.graphic_objects.textObject.FormattedText;
30 import org.scilab.modules.renderer.JoGLView.util.ColorFactory;
31 import org.scilab.modules.renderer.JoGLView.util.FormattedTextSpriteDrawer;
32 import org.scilab.modules.renderer.utils.textRendering.FontManager;
33 
34 import java.awt.Dimension;
35 import java.awt.Font;
36 import java.text.DecimalFormat;
37 import java.text.DecimalFormatSymbols;
38 
39 /**
40  * This implementation of {@see RulerSpriteFactory} create ruler labels for the given {@see Axes}.
41  *
42  * @author Pierre Lando
43  */
44 public class AxesRulerSpriteFactory implements RulerSpriteFactory {
45     /**
46      * The symbol used for ticks label in log and auto ticks mode.
47      */
48     private static final String MULTIPLICATION_SYMBOL = "x";
49 
50     /**
51      * The exponent size is smaller than the mantissa size.
52      */
53     private static final float EXPONENT_SIZE_RATIO = 0.4f;
54 
55     /**
56      * This factory create ruler label for this {@see Axis}.
57      */
58     private final AxisProperty axisProperty;
59 
60     /**
61      * The current colormap.
62      */
63     private final ColorMap colorMap;
64 
65     /**
66      * Default constructor.
67      * @param axes This factory create ruler label for one axis of this given {@see Axes}.
68      * @param axisId the id of the managed axis.
69      */
AxesRulerSpriteFactory(Axes axes, int axisId)70     public AxesRulerSpriteFactory(Axes axes, int axisId) {
71         this.axisProperty = axes.getAxes()[axisId];
72         ColorMap figureColorMap;
73         try {
74             GraphicController controller = GraphicController.getController();
75             AxesContainer parentFigure = (AxesContainer) controller.getObjectFromId(axes.getParentFigure());
76             figureColorMap = parentFigure.getColorMap();
77         } catch (NullPointerException e) {
78             figureColorMap = null;
79         }
80         this.colorMap = figureColorMap;
81     }
82 
83     @Override
create(double value, DecimalFormat adaptedFormat, TextureManager textureManager)84     public Texture create(double value, DecimalFormat adaptedFormat, TextureManager textureManager) {
85         // Simple ack to avoid ticks with "-0" as label.
86         if (value == -0) {
87             value = 0;
88         }
89 
90         if (axisProperty.getAutoTicks()) {
91             setScilabStyle(adaptedFormat);
92             if (axisProperty.getLogFlag()) {
93                 return createScientificStyleSprite(value, textureManager);
94             } else {
95                 return createSimpleSprite(adaptedFormat.format(value), textureManager);
96             }
97         } else {
98             FormattedText formattedText = getTextAtValue(value);
99             if (formattedText != null && formattedText.getText() != null && !formattedText.getText().isEmpty()) {
100                 FormattedTextSpriteDrawer textObjectSpriteDrawer = new FormattedTextSpriteDrawer(colorMap, formattedText);
101                 Texture texture = textureManager.createTexture();
102                 texture.setMagnificationFilter(Texture.Filter.LINEAR);
103                 texture.setMinifyingFilter(Texture.Filter.LINEAR);
104                 texture.setDrawer(textObjectSpriteDrawer);
105 
106                 return texture;
107             }
108 
109             return null;
110         }
111     }
112 
113     /**
114      * Set the given {@see DecimalFormat} to scilab style.
115      * @param format the given {@see DecimalFormat}.
116      */
setScilabStyle(DecimalFormat format)117     public static void setScilabStyle(DecimalFormat format) {
118         DecimalFormatSymbols decimalFormatSymbols = format.getDecimalFormatSymbols();
119         decimalFormatSymbols.setDecimalSeparator('.');
120         decimalFormatSymbols.setExponentSeparator("e");
121         decimalFormatSymbols.setGroupingSeparator('\u00A0');
122         format.setDecimalFormatSymbols(decimalFormatSymbols);
123     }
124 
125     /**
126      * Create and return a texture representing the given value.|| index >= axisProperty.getTicksLabels().size()
127      * The returned sprites will look like "5x10^2"
128      * @param value, the given value.
129      * @param textureManager used texture manager.
130      * @return a simple texture representing the given value with the adapted format.
131      */
createScientificStyleSprite(double value, TextureManager textureManager)132     private Texture createScientificStyleSprite(double value, TextureManager textureManager) {
133         Integer exponent = (int) Math.floor(Math.log10(value));
134         Double mantissa = value / Math.pow(10, exponent);
135         mantissa = Math.round(mantissa * 1e6) * 1e-6;
136 
137         /**
138          * Create mantissa.
139          */
140         final TextEntity mantissaTextEntity;
141         if (mantissa != 1) {
142             mantissaTextEntity = new TextEntity(mantissa.toString() + MULTIPLICATION_SYMBOL + "10");
143         } else {
144             mantissaTextEntity = new TextEntity("10");
145         }
146 
147         Font mantissaFont = FontManager.getSciFontManager().getFontFromIndex(axisProperty.getFontStyle(), axisProperty.getFontSize());
148         mantissaTextEntity.setTextAntiAliased(true);
149         mantissaTextEntity.setTextUseFractionalMetrics(axisProperty.getFontFractional());
150         mantissaTextEntity.setTextColor(ColorFactory.createColor(colorMap, axisProperty.getFontColor()));
151         mantissaTextEntity.setFont(mantissaFont);
152         final Dimension mantissaSize = mantissaTextEntity.getSize();
153 
154         /**
155          * Create exponent.
156          */
157         final TextEntity exponentTextEntity = new TextEntity(exponent.toString());
158         Font exponentFont = FontManager.getSciFontManager().getFontFromIndex(axisProperty.getFontStyle(), axisProperty.getFontSize() * EXPONENT_SIZE_RATIO);
159         exponentTextEntity.setTextAntiAliased(true);
160         exponentTextEntity.setTextUseFractionalMetrics(axisProperty.getFontFractional());
161         exponentTextEntity.setTextColor(ColorFactory.createColor(colorMap, axisProperty.getFontColor()));
162         exponentTextEntity.setFont(exponentFont);
163         final int exponentHeight = (int) exponentTextEntity.getLayout().getBounds().getHeight();
164         final Dimension exponentSize = exponentTextEntity.getSize();
165 
166         Texture texture = textureManager.createTexture();
167 
168         texture.setDrawer(new TextureDrawer() {
169 
170             @Override
171             public void draw(TextureDrawingTools drawingTools) {
172                 drawingTools.draw(mantissaTextEntity, 0, exponentHeight);
173                 drawingTools.draw(exponentTextEntity, mantissaSize.width, 0);
174             }
175 
176             @Override
177             public Dimension getTextureSize() {
178                 return new Dimension(
179                            exponentSize.width + mantissaSize.width,
180                            exponentHeight + mantissaSize.height
181                        );
182             }
183 
184             @Override
185             public TextureDrawer.OriginPosition getOriginPosition() {
186                 return TextureDrawer.OriginPosition.UPPER_LEFT;
187             }
188         });
189 
190         return texture;
191     }
192 
193     /**
194      * Create and return a simple texture representing the given value.
195      * @param text the formatted string representing the value.
196      * @param textureManager used texture manager.
197      * @return a simple texture representing the given value with the adapted format.
198      */
createSimpleSprite(String text, TextureManager textureManager)199     private Texture createSimpleSprite(String text, TextureManager textureManager) {
200         if (FormattedTextSpriteDrawer.isLatex(text) || FormattedTextSpriteDrawer.isMathML(text)) {
201             FormattedTextSpriteDrawer textObjectSpriteDrawer = new FormattedTextSpriteDrawer(colorMap, text, axisProperty.getTicks().getDefaultFont());
202             Texture texture = textureManager.createTexture();
203             texture.setMagnificationFilter(Texture.Filter.LINEAR);
204             texture.setMinifyingFilter(Texture.Filter.LINEAR);
205             texture.setDrawer(textObjectSpriteDrawer);
206 
207             return texture;
208         }
209 
210         Font font = FontManager.getSciFontManager().getFontFromIndex(axisProperty.getFontStyle(), axisProperty.getFontSize());
211         final TextEntity textEntity = new TextEntity(text);
212         textEntity.setTextAntiAliased(true);
213         textEntity.setTextUseFractionalMetrics(axisProperty.getFontFractional());
214         textEntity.setTextColor(ColorFactory.createColor(colorMap, axisProperty.getFontColor()));
215         textEntity.setFont(font);
216 
217         Texture texture = textureManager.createTexture();
218         texture.setDrawer(new TextureDrawer() {
219 
220             @Override
221             public void draw(TextureDrawingTools drawingTools) {
222                 drawingTools.draw(textEntity, 0, 0);
223             }
224 
225             @Override
226             public Dimension getTextureSize() {
227                 return textEntity.getSize();
228             }
229 
230             @Override
231             public TextureDrawer.OriginPosition getOriginPosition() {
232                 return TextureDrawer.OriginPosition.UPPER_LEFT;
233             }
234         });
235 
236         return texture;
237     }
238 
239     /**
240      * Return the user defined {@see FormattedText} ticks label corresponding to the given value.
241      * @param value the given value.
242      * @return the user defined {@see FormattedText} ticks label corresponding to the given value.
243      */
getTextAtValue(double value)244     private FormattedText getTextAtValue(double value) {
245         Double[] locations = axisProperty.getTicksLocations();
246         int index = -1;
247         for (int i = 0 ; i < locations.length ; i++) {
248             if (locations[i] == value) {
249                 index = i;
250                 break;
251             }
252         }
253         if (index == -1 || index >= axisProperty.getTicksLabels().size()) {
254             return null;
255         } else {
256             return axisProperty.getTicksLabels().get(index);
257         }
258     }
259 }
260