Bug 4743 fixed: Invalid graphics with too big or too small values
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / text / TextManager.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2010 - DIGITEO - Pierre Lando
4  * Copyright (C) 2012 - DIGITEO - Manuel Juliachs
5  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  */
12
13 package org.scilab.modules.renderer.JoGLView.text;
14
15 import org.scilab.forge.scirenderer.DrawingTools;
16 import org.scilab.forge.scirenderer.SciRendererException;
17 import org.scilab.forge.scirenderer.texture.AnchorPosition;
18 import org.scilab.forge.scirenderer.texture.Texture;
19 import org.scilab.forge.scirenderer.texture.TextureManager;
20 import org.scilab.forge.scirenderer.tranformations.DegenerateMatrixException;
21 import org.scilab.forge.scirenderer.tranformations.Transformation;
22 import org.scilab.forge.scirenderer.tranformations.TransformationFactory;
23 import org.scilab.forge.scirenderer.tranformations.Vector3d;
24 import org.scilab.modules.graphic_objects.axes.Axes;
25 import org.scilab.modules.graphic_objects.figure.ColorMap;
26 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
27 import org.scilab.modules.graphic_objects.textObject.Text;
28 import org.scilab.modules.renderer.JoGLView.DrawerVisitor;
29 import org.scilab.modules.renderer.JoGLView.util.ScaleUtils;
30
31 import java.awt.Dimension;
32 import java.util.Map;
33 import java.util.concurrent.ConcurrentHashMap;
34
35 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_FONT_ANGLE__;
36 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_POSITION__;
37
38 /**
39  *
40  * This class manage scilab text entity drawing.
41  *
42  *
43  * TODO, Manage: {auto_dimensionning}
44  *
45  *
46  * @author Pierre Lando
47  */
48 public class TextManager {
49
50     /**
51      * The {@see Map} off existing {@see TextEntity}.
52      */
53     protected final Map<String, Texture> spriteMap = new ConcurrentHashMap<String, Texture>();
54
55     /**
56      * The used texture manager.
57      */
58     protected final TextureManager textureManager;
59
60     /**
61      * The bounds of the scale factor range for which the texture does not
62      * need to be updated.
63      */
64     protected double[] FACTOR_UPDATE_INTERVAL = {0.99, 1.01};
65
66     /**
67      * Default constructor.
68      * @param textureManager the texture manager.
69      */
70     public TextManager(TextureManager textureManager) {
71         this.textureManager = textureManager;
72     }
73
74     /**
75      * Draw the given Scilab {@see Text} with the given {@see DrawingTools}.
76      * @param drawingTools the given {@see DrawingTools}.
77      * @param colorMap the current {@see ColorMap}
78      * @param text the given Scilab {@see Text}
79      * @throws SciRendererException if the draw fails.
80      */
81     public final void draw(final DrawingTools drawingTools, final ColorMap colorMap, final Text text) throws SciRendererException {
82         Texture texture = getTexture(colorMap, text);
83
84         /* The unscaled texture's dimensions */
85         Dimension spriteDims = getSpriteDims(colorMap, text);
86
87         Transformation projection = drawingTools.getTransformationManager().getCanvasProjection();
88
89         String parentAxesId = text.getParentAxes();
90         Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(parentAxesId);
91         double[][] factors = parentAxes.getScaleTranslateFactors();
92         Double[] pos = text.getPosition();
93         pos[0] = pos[0] * factors[0][0] + factors[1][0];
94         pos[1] = pos[1] * factors[0][1] + factors[1][1];
95         pos[2] = pos[2] * factors[0][2] + factors[1][2];
96
97         Vector3d textPosition = new Vector3d(pos);
98
99         /* Compute the text box vectors and the text box to texture dimension ratios */
100         Vector3d[] textBoxVectors =  computeTextBoxVectors(projection, text, texture.getDataProvider().getTextureSize(), parentAxes);
101         double[] ratios = computeRatios(projection, text, textBoxVectors, texture.getDataProvider().getTextureSize(), spriteDims);
102
103         /* If text box mode is equal to filled, the texture must be updated */
104         if (text.getTextBoxMode() == 2 && ratios[0] != 1.0) {
105             texture = updateSprite(colorMap, text, ratios[0], ratios[1]);
106         }
107
108         /* Compute the text texture's actual position, which depends on the object's text box mode property */
109         Vector3d[] cornerPositions = computeTextPosition(projection, text, textBoxVectors, texture.getDataProvider().getTextureSize());
110
111         /* Draw in window coordinates */
112         drawingTools.getTransformationManager().useWindowCoordinate();
113
114         /* The Text object's rotation direction convention is opposite to the standard one, its angle is expressed in radians. */
115         drawingTools.draw(texture, AnchorPosition.LOWER_LEFT, cornerPositions[0], -180.0 * text.getFontAngle() / Math.PI);
116
117         drawingTools.getTransformationManager().useSceneCoordinate();
118
119         /* Compute the corners of the text's bounding box in window coordinates */
120         Vector3d[] projCorners;
121         if (text.getTextBoxMode() == 2) {
122             projCorners = computeProjTextBoxCorners(cornerPositions[1], text.getFontAngle(), textBoxVectors);
123         } else {
124             projCorners = computeProjCorners(cornerPositions[0], text.getFontAngle(), texture.getDataProvider().getTextureSize());
125         }
126
127         Vector3d[] corners = computeCorners(projection, projCorners, parentAxes);
128         Double[] coordinates = cornersToCoordinateArray(corners);
129
130         /* Set the computed coordinates */
131         text.setCorners(coordinates);
132     }
133
134     /**
135      * Computes and returns the two vectors (in window coordinates) respectively corresponding
136      * to the text box's base and side (also named the text box width and height vectors). If the
137      * Text's text box mode is equal to off, the vectors are then equal to the Text label's base
138      * and side vectors.  The Text's rotation is ignored, as it is not required for now.
139      * @param projection the projection from object coordinates to window coordinates.
140      * @param text the Scilab {@see Text}.
141      * @param dimension the current text texture's dimension (in pixels).
142      * @param parentAxes the Axes for which the coordinates are computed.
143      * @return the text box width and height vectors (in window coordinates).
144      */
145     protected Vector3d[] computeTextBoxVectors(Transformation projection, Text text, Dimension dimension, Axes parentAxes) {
146         Double[] textBox = text.getTextBox();
147
148         Vector3d[] textBoxVectors = new Vector3d[2];
149
150         double[][] factors = parentAxes.getScaleTranslateFactors();
151         Double[] pos = text.getPosition();
152         pos[0] = pos[0] * factors[0][0] + factors[1][0];
153         pos[1] = pos[1] * factors[0][1] + factors[1][1];
154         pos[2] = pos[2] * factors[0][2] + factors[1][2];
155
156         /* The text position vector before logarithmic scaling */
157         Vector3d unscaledTextPosition = new Vector3d(pos);
158
159         boolean[] logFlags = new boolean[] {parentAxes.getXAxisLogFlag(), parentAxes.getYAxisLogFlag(), parentAxes.getZAxisLogFlag()};
160
161         /* Apply logarithmic scaling and then project */
162         Vector3d textPosition = ScaleUtils.applyLogScale(unscaledTextPosition, logFlags);
163         Vector3d projTextPosition = projection.project(textPosition);
164
165         /* Compute the text label vectors in window coordinates */
166         Vector3d width = new Vector3d(dimension.getWidth(), 0.0, 0.0);
167         Vector3d height = new Vector3d(0.0, dimension.getHeight(), 0.0);
168
169         Vector3d projTextWidth = projTextPosition.plus(width);
170         Vector3d projTextHeight = projTextPosition.plus(height);
171
172         /*
173          * Compute the text box's vectors in object coordinates, from the object coordinate text label vectors.
174          * Their norms are unaffected by the text's rotation, which is thus ignored.
175          */
176         Vector3d textWidth = projection.unproject(projTextWidth);
177         Vector3d textHeight = projection.unproject(projTextHeight);
178
179         /* Applies inverse logarithmic scaling */
180         textWidth = ScaleUtils.applyInverseLogScale(textWidth, logFlags);
181         textHeight = ScaleUtils.applyInverseLogScale(textHeight, logFlags);
182
183
184         textWidth = textWidth.minus(unscaledTextPosition);
185         textHeight = textHeight.minus(unscaledTextPosition);
186
187         if (text.getTextBoxMode() >= 1) {
188             textWidth = textWidth.getNormalized().times(textBox[0]);
189             textHeight = textHeight.getNormalized().times(textBox[1]);
190         }
191
192         /*
193          * We take into account the reverse axes flags in order to
194          * compute the actual text box corners, and hence the correct vectors,
195          * which is necessary when logarithmic scaling is applied.
196          */
197         if (parentAxes.getXAxisReverse()) {
198             textWidth = textWidth.setX(Math.abs(textWidth.getX()));
199             textHeight = textHeight.setX(Math.abs(textHeight.getX()));
200         }
201         if (parentAxes.getYAxisReverse()) {
202             textWidth = textWidth.setY(Math.abs(textWidth.getY()));
203             textHeight = textHeight.setY(Math.abs(textHeight.getY()));
204         }
205         if (parentAxes.getZAxisReverse()) {
206             textWidth = textWidth.setZ(Math.abs(textWidth.getZ()));
207             textHeight = textHeight.setZ(Math.abs(textHeight.getZ()));
208         }
209
210         /* Computes the lower-right and upper-left corners. */
211         textWidth = textWidth.plus(unscaledTextPosition);
212         textHeight = textHeight.plus(unscaledTextPosition);
213
214         /* Finally re-apply logarithmic scaling, compute the vectors and project */
215         textWidth = ScaleUtils.applyLogScale(textWidth, logFlags);
216         textHeight = ScaleUtils.applyLogScale(textHeight, logFlags);
217
218         textWidth = textWidth.minus(textPosition);
219         textHeight = textHeight.minus(textPosition);
220
221         projTextWidth = projection.projectDirection(textWidth);
222         projTextHeight = projection.projectDirection(textHeight);
223
224         /*
225          * Ensures that the two window-coordinate base vectors respectively point to the right
226          * and to the top, as taking reversed axes into account may have reversed them (see above).
227          */
228         projTextWidth = projTextWidth.setX(Math.abs(projTextWidth.getX()));
229         projTextHeight = projTextHeight.setX(Math.abs(projTextHeight.getX()));
230         projTextWidth = projTextWidth.setY(Math.abs(projTextWidth.getY()));
231         projTextHeight = projTextHeight.setY(Math.abs(projTextHeight.getY()));
232
233         textBoxVectors[0] = projTextWidth;
234         textBoxVectors[1] = projTextHeight;
235
236         return textBoxVectors;
237     }
238
239     /**
240      * Computes and returns the minimum of the ratios between the text box and the text texture's dimensions.
241      * This minimum ratio is determined for both the current text texture and the unscaled text texture.
242      * @param projection the projection from object coordinates to window coordinates.
243      * @param text the Scilab {@see Text}.
244      * @param textBoxVectors the text box width and height vectors (in window coordinates).
245      * @param spriteDimension the current text texture's dimension (in pixels).
246      * @param baseSpriteDimension the unscaled text texture's dimension (in pixels).
247      * @return the minimum ratios (2 elements: text box to current texture and text box to unscaled texture ratios).
248      */
249     protected double[] computeRatios(Transformation projection, Text text, Vector3d[] textBoxVectors, Dimension spriteDimension,
250                                    Dimension baseSpriteDimension) {
251         /* 1st element: ratio for the current texture, 2nd element: ratio for the unscaled texture */
252         double[] ratios = new double[] {1.0, 1.0};
253
254         /* Ratios are relevant only to the filled text box mode */
255         if (text.getTextBoxMode() == 2) {
256             Vector3d textBoxWidth = textBoxVectors[0];
257             Vector3d textBoxHeight = textBoxVectors[1];
258
259             /* Compute the ratios. */
260             double minRatio = Math.min(Math.abs(textBoxWidth.getX() / spriteDimension.width), Math.abs(textBoxHeight.getY() / spriteDimension.height));
261             double baseMinRatio = Math.min(Math.abs(textBoxWidth.getX() / baseSpriteDimension.width), Math.abs(textBoxHeight.getY() / baseSpriteDimension.height));
262
263             ratios[0] = minRatio;
264             ratios[1] = baseMinRatio;
265         }
266
267         return ratios;
268     }
269
270     /**
271      * Computes and returns the positions of a Scilab {@see Text} object and its text box in window coordinates, as a function
272      * of its text box mode and text box properties. They are the position of the Text's lower-left corner,
273      * which may differ from the text's unmodified position, depending on its text box properties, and
274      * the position of the text box's lower-left corner. If the text box mode is set to off, the text lower-left corner's position
275      * is simply the text's projected position, and its text box's position is equal to the former.
276      * @param projection the projection from object coordinates to window coordinates.
277      * @param text the Scilab {@see Text}.
278      * @param textBoxVectors the text box width and height vectors (in window coordinates).
279      * @param spriteDim the text texture's dimension (in pixels).
280      * @return the lower-left corners of the Scilab {@see Text}'s text and of its text box in window coordinates (2 elements).
281      * @throws DegenerateMatrixException if the projection is not possible.
282      */
283     protected Vector3d[] computeTextPosition(Transformation projection, Text text, Vector3d[] textBoxVectors, Dimension spriteDim) throws DegenerateMatrixException {
284         Vector3d[] cornerPositions = new Vector3d[2];
285
286         String parentAxesId = text.getParentAxes();
287         Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(parentAxesId);
288         double[][] factors = parentAxes.getScaleTranslateFactors();
289         Double[] pos = text.getPosition();
290         pos[0] = pos[0] * factors[0][0] + factors[1][0];
291         pos[1] = pos[1] * factors[0][1] + factors[1][1];
292         pos[2] = pos[2] * factors[0][2] + factors[1][2];
293
294         Vector3d textPosition = new Vector3d(pos);
295
296         /* Apply logarithmic scaling */
297         boolean[] logFlags = new boolean[] {parentAxes.getXAxisLogFlag(), parentAxes.getYAxisLogFlag(), parentAxes.getZAxisLogFlag()};
298         textPosition = ScaleUtils.applyLogScale(textPosition, logFlags);
299
300         textPosition = projection.project(textPosition);
301
302         cornerPositions[0] = new Vector3d(textPosition);
303         cornerPositions[1] = new Vector3d(textPosition);
304
305         if (text.getTextBoxMode() >= 1) {
306             Double[] textBox = text.getTextBox();
307
308             Vector3d textBoxWidth = new Vector3d(textBoxVectors[0]);
309             Vector3d textBoxHeight = new Vector3d(textBoxVectors[1]);
310
311             double[] textBoxWidthData = textBoxWidth.getData();
312             double[] textBoxHeightData = textBoxHeight.getData();
313
314             /* Reversed axes must be taken into account to correctly compute the text texture's lower-left corner. */
315             if (parentAxes.getXAxisReverse()) {
316                 textBoxWidthData[0] = -textBoxWidthData[0];
317                 textBoxHeightData[0] = -textBoxHeightData[0];
318             }
319
320             if (parentAxes.getYAxisReverse()) {
321                 textBoxWidthData[1] = -textBoxWidthData[1];
322                 textBoxHeightData[1] = -textBoxHeightData[1];
323             }
324
325             if (parentAxes.getZAxisReverse()) {
326                 textBoxWidthData[2] = -textBoxWidthData[2];
327                 textBoxHeightData[2] = -textBoxHeightData[2];
328             }
329
330             Vector3d revTextBoxWidth = new Vector3d(textBoxWidthData);
331             Vector3d revTextBoxHeight = new Vector3d(textBoxHeightData);
332
333             Vector3d[] projCorners = computeProjCorners(textPosition, text.getFontAngle(), spriteDim);
334
335             Vector3d textWidth = projCorners[1].minus(projCorners[0]);
336             Vector3d textHeight = projCorners[2].minus(projCorners[0]);
337
338             /*
339              * Compute the final text box's and text's half-length vectors,
340              * using the rotated text label vectors.
341              */
342             revTextBoxWidth = textWidth.getNormalized().times(0.5 * revTextBoxWidth.getX());
343             revTextBoxHeight = textHeight.getNormalized().times(0.5 * revTextBoxHeight.getY());
344
345             textBoxWidth = textWidth.getNormalized().times(0.5 * textBoxWidth.getX());
346             textBoxHeight = textHeight.getNormalized().times(0.5 * textBoxHeight.getY());
347
348             textWidth = textWidth.times(0.5);
349             textHeight = textHeight.times(0.5);
350
351             /* Compute the actual corner positions from the initial projected position and the half-length vectors */
352             textPosition = textPosition.plus(revTextBoxWidth);
353             textPosition = textPosition.plus(revTextBoxHeight);
354
355             Vector3d textBoxCorner = textPosition.minus(textBoxWidth);
356             textBoxCorner = textBoxCorner.minus(textBoxHeight);
357
358             textPosition = textPosition.minus(textWidth);
359             textPosition = textPosition.minus(textHeight);
360
361             cornerPositions[0] = textPosition;
362             cornerPositions[1] = textBoxCorner;
363         }
364
365         return cornerPositions;
366     }
367
368     /**
369      * Computes and returns the corners of a {@see Text} object's bounding box, in window coordinates.
370      * The returned corners are in the following order: lower-left, lower-right, upper-left and upper-right.
371      * @param canvasProj the projection from object coordinates to window coordinates.
372      * @param position the text's position in object coordinates.
373      * @param fontAngle the text's font angle (radians).
374      * @param spriteDim the text texture's dimension (in pixels).
375      * @return the corners' window coordinates (4-element array).
376      * @throws DegenerateMatrixException if the projection is not possible.
377      */
378     protected Vector3d[] computeProjCorners(Transformation canvasProj, Vector3d position, double fontAngle, Dimension spriteDim) throws DegenerateMatrixException {
379         position = canvasProj.project(position);
380         return computeProjCorners(position, fontAngle, spriteDim);
381     }
382
383     /**
384      * Computes the corners of a {@see Text} object's text box, in window coordinates.
385      * @param position the position of the text box's lower-left corner in window cordinates.
386      * @param fontAngle the text's font angle (radians).
387      * @param textBoxVectors the text box width and height vectors (in window coordinates).
388      * @return the corners' window coordinates (4-element array).
389      * @throws DegenerateMatrixException if the projection is not possible.
390      */
391     protected Vector3d[] computeProjTextBoxCorners(Vector3d position, double fontAngle, Vector3d[] textBoxVectors) throws DegenerateMatrixException {
392         double projTextBoxWidth = textBoxVectors[0].getNorm();
393         double projTextBoxHeight = textBoxVectors[1].getNorm();
394
395         return computeProjCorners(position, fontAngle, new Dimension((int) projTextBoxWidth, (int) projTextBoxHeight));
396     }
397
398     /**
399      * Computes and returns the corners of a {@see Text} object's bounding box, in window coordinates.
400      * The returned corners are in the following order: lower-left, lower-right, upper-left and upper-right.
401      * @param projPosition the text's position in window coordinates.
402      * @param fontAngle the text's font angle (radians).
403      * @param spriteDim the text texture's dimension (in pixels).
404      * @return the corners' window coordinates (4-element array).
405      * @throws DegenerateMatrixException if the projection is not possible.
406      */
407     protected Vector3d[] computeProjCorners(Vector3d projPosition, double fontAngle, Dimension spriteDim) throws DegenerateMatrixException {
408         Vector3d[] projCorners = new Vector3d[4];
409
410         /*
411          * Should be -fontAngle, as positive angle values are measured clockwise for texts.
412          * Apparently uses the same convention as the texts (clockwise positive directions).
413          * To be verified.
414          */
415         Transformation projRotation = TransformationFactory.getRotationTransformation(180.0 * fontAngle / Math.PI, 0.0, 0.0, 1.0);
416
417         projCorners[0] = projPosition;
418
419         Vector3d width = new Vector3d(spriteDim.width, 0.0, 0.0);
420         Vector3d height = new Vector3d(0.0, spriteDim.height, 0.0);
421
422         width = projRotation.projectDirection(width);
423         height = projRotation.projectDirection(height);
424
425         projCorners[1] = projCorners[0].plus(width);
426         projCorners[2] = projCorners[0].plus(height);
427         projCorners[3] = projCorners[2].plus(width);
428
429         return projCorners;
430     }
431
432     /**
433      * Computes and returns the corners (in user coordinates) of a text's bounding box.
434      * @param projection the projection from object coordinates to window coordinates.
435      * @param projCorners the corners of the text's bounding box in window coordinates (4-element array).
436      * @param parentAxes the Axes for which the coordinates are computed.
437      * @return the corners of the text's bounding box in user coordinates (4-element array).
438      */
439     protected Vector3d[] computeCorners(Transformation projection, Vector3d[] projCorners, Axes parentAxes) {
440         Vector3d[] corners = new Vector3d[4];
441         boolean[] logFlags = new boolean[] {parentAxes.getXAxisLogFlag(), parentAxes.getYAxisLogFlag(), parentAxes.getZAxisLogFlag()};
442
443         corners[0] = projection.unproject(projCorners[0]);
444         corners[1] = projection.unproject(projCorners[1]);
445         corners[2] = projection.unproject(projCorners[2]);
446         corners[3] = projection.unproject(projCorners[3]);
447
448         /* Apply inverse logarithmic scaling in order to obtain user coordinates */
449         corners[0] = ScaleUtils.applyInverseLogScale(corners[0], logFlags);
450         corners[1] = ScaleUtils.applyInverseLogScale(corners[1], logFlags);
451         corners[2] = ScaleUtils.applyInverseLogScale(corners[2], logFlags);
452         corners[3] = ScaleUtils.applyInverseLogScale(corners[3], logFlags);
453
454         return corners;
455     }
456
457     /**
458      * Returns the positions of a bounding box's corners as an array of (x,y,z) coordinate triplets.
459      * The output corners are reordered to match their order in the {@see Text} object's
460      * equivalent array, respectively: lower-left, lower-right, upper-left, upper-right in the input array,
461      * starting from the lower-left and going in clockwise order in the returned array.
462      * @param corners of the bounding box (4-element array).
463      * @return the corners' coordinates (12-element array).
464      */
465     protected Double[] cornersToCoordinateArray(Vector3d[] corners) {
466         Double[] coordinates = new Double[12];
467         coordinates[0] = corners[0].getX();
468         coordinates[1] = corners[0].getY();
469         coordinates[2] = corners[0].getZ();
470
471         coordinates[3] = corners[2].getX();
472         coordinates[4] = corners[2].getY();
473         coordinates[5] = corners[2].getZ();
474
475         coordinates[6] = corners[3].getX();
476         coordinates[7] = corners[3].getY();
477         coordinates[8] = corners[3].getZ();
478
479         coordinates[9] = corners[1].getX();
480         coordinates[10] = corners[1].getY();
481         coordinates[11] = corners[1].getZ();
482
483         return coordinates;
484     }
485
486
487     /**
488      * Update the data if needed.
489      * @param id the modified object.
490      * @param property the changed property.
491      */
492     public void update(String id, int property) {
493         if (!(__GO_POSITION__ == property) && !(__GO_FONT_ANGLE__ == property)) {
494             dispose(id);
495         }
496     }
497
498     /**
499      * Return the SciRenderer {@see Texture} corresponding to the given Scilab {@see Text}.
500      * @param colorMap the current color map.
501      * @param text the given Scilab {@see Text}.
502      * @return the SciRenderer {@see Texture} corresponding to the given Scilab {@see Text}.
503      */
504     protected Texture getTexture(final ColorMap colorMap, final Text text) {
505         Texture texture = spriteMap.get(text.getIdentifier());
506         if (texture == null) {
507             if (text.getTextBoxMode() == 2) {
508                 /* Create an unscaled texture (scale factor equal to 1) */
509                 texture = createSprite(colorMap, text, 1.0);
510             } else {
511                 texture = createSprite(colorMap, text);
512             }
513             spriteMap.put(text.getIdentifier(), texture);
514         }
515         return texture;
516     }
517
518     /**
519      * Updates a texture according to a scale factor, which is the ratio by which the texture is enlarged.
520      * @param colorMap the current color map.
521      * @param text the Scilab Text.
522      * @param scaleFactor the scale factor relative to the current texture's dimensions.
523      * @param baseScaleFactor the scale factor relative to the unscaled texture's dimensions.
524      * @return the corresponding texture.
525      */
526     protected Texture updateSprite(final ColorMap colorMap, final Text text, double scaleFactor, double baseScaleFactor) {
527         Texture texture = spriteMap.get(text.getIdentifier());
528
529         /* Create a new texture if the scale factor falls outside of the range */
530         if (scaleFactor < FACTOR_UPDATE_INTERVAL[0] || scaleFactor > FACTOR_UPDATE_INTERVAL[1]) {
531             dispose(text.getIdentifier());
532             texture = createSprite(colorMap, text, baseScaleFactor);
533             spriteMap.put(text.getIdentifier(), texture);
534         }
535
536         return texture;
537     }
538
539     /**
540      * Returns the dimensions of the SciRenderer {@see Texture} corresponding to the given Scilab {@see Text}.
541      * The dimensions are in pixels (width, height).
542      * @param colorMap the current color map.
543      * @param text the given Scilab {@see Text}.
544      * @return the texture's dimension.
545      */
546     protected Dimension getSpriteDims(final ColorMap colorMap, final Text text) {
547         TextSpriteDrawer spriteDrawer;
548
549         if (text.getTextBoxMode() == 2) {
550             /* Set the scale factor to 1 in order to return the dimensions of an unscaled texture. */
551             spriteDrawer = new TextSpriteDrawer(colorMap, text, 1.0);
552         } else {
553             spriteDrawer = new TextSpriteDrawer(colorMap, text);
554         }
555
556         return spriteDrawer.getTextureSize();
557     }
558
559     /**
560      * Create a texture for the given text object.
561      * @param colorMap the current colormap.
562      * @param textObject the given text object.
563      * @return a new texture for the given text object.
564      */
565     protected Texture createSprite(final ColorMap colorMap, final Text textObject) {
566         TextSpriteDrawer spriteDrawer = new TextSpriteDrawer(colorMap, textObject);
567         Texture texture = textureManager.createTexture();
568         texture.setMagnificationFilter(Texture.Filter.LINEAR);
569         texture.setMinifyingFilter(Texture.Filter.LINEAR);
570         texture.setDrawer(spriteDrawer);
571         return texture;
572     }
573
574     /**
575      * Creates a texture for the given text object, scaled by the given scale factor.
576      * @param colorMap the current colormap.
577      * @param textObject the given text object.
578      * @param scaleFactor the scale factor to apply.
579      * @return a new texture for the given text object.
580      */
581     protected Texture createSprite(final ColorMap colorMap, final Text textObject, double scaleFactor) {
582         TextSpriteDrawer spriteDrawer = new TextSpriteDrawer(colorMap, textObject, scaleFactor);
583         Texture texture = textureManager.createTexture();
584         texture.setMagnificationFilter(Texture.Filter.LINEAR);
585         texture.setMinifyingFilter(Texture.Filter.LINEAR);
586         texture.setDrawer(spriteDrawer);
587         return texture;
588     }
589
590     /**
591      * Dispose the texture corresponding to the given id.
592      * @param id the given id.
593      */
594     public void dispose(String id) {
595         Texture texture = spriteMap.get(id);
596         if (texture != null) {
597             textureManager.dispose(texture);
598             spriteMap.remove(id);
599         }
600     }
601
602     /**
603      * Dispose all the text sprites.
604      */
605     public void disposeAll() {
606         textureManager.dispose(spriteMap.values());
607         spriteMap.clear();
608     }
609
610     /**
611      * Computes and updates the corners of the given Scilab {@see Text}.
612      * @param text the given Scilab {@see Text}.
613      */
614     public static void updateTextCorners(Text text) {
615         Vector3d[] projCorners = null;
616
617         DrawerVisitor currentVisitor = DrawerVisitor.getVisitor(text.getParentFigure());
618         Axes parentAxes = (Axes) GraphicController.getController().getObjectFromId(text.getParentAxes());
619
620         /* Compute the corners */
621         try {
622             Transformation currentProj = currentVisitor.getAxesDrawer().getCurrentProjection(parentAxes);
623
624             Dimension spriteDim = currentVisitor.getTextManager().getSpriteDims(currentVisitor.getColorMap(), text);
625
626             Vector3d[] textBoxVectors = currentVisitor.getTextManager().computeTextBoxVectors(currentProj, text, spriteDim, parentAxes);
627             Vector3d[] cornerPositions = currentVisitor.getTextManager().computeTextPosition(currentProj, text, textBoxVectors, spriteDim);
628
629             if (text.getTextBoxMode() == 2) {
630                 projCorners = currentVisitor.getTextManager().computeProjTextBoxCorners(cornerPositions[1], text.getFontAngle(), textBoxVectors);
631             } else {
632                 projCorners = currentVisitor.getTextManager().computeProjCorners(cornerPositions[0], text.getFontAngle(), spriteDim);
633             }
634
635             Vector3d[] corners = currentVisitor.getTextManager().computeCorners(currentProj, projCorners, parentAxes);
636             Double[] coordinates = currentVisitor.getTextManager().cornersToCoordinateArray(corners);
637
638             double[][] factors = parentAxes.getScaleTranslateFactors();
639             coordinates[0] = (coordinates[0] - factors[1][0]) / factors[0][0];
640             coordinates[1] = (coordinates[1] - factors[1][1]) / factors[0][1];
641             coordinates[2] = (coordinates[2] - factors[1][2]) / factors[0][2];
642             coordinates[3] = (coordinates[3] - factors[1][0]) / factors[0][0];
643             coordinates[4] = (coordinates[4] - factors[1][1]) / factors[0][1];
644             coordinates[5] = (coordinates[5] - factors[1][2]) / factors[0][2];
645             coordinates[6] = (coordinates[6] - factors[1][0]) / factors[0][0];
646             coordinates[7] = (coordinates[7] - factors[1][1]) / factors[0][1];
647             coordinates[8] = (coordinates[8] - factors[1][2]) / factors[0][2];
648             coordinates[9] = (coordinates[9] - factors[1][0]) / factors[0][0];
649             coordinates[10] = (coordinates[10] - factors[1][1]) / factors[0][1];
650             coordinates[11] = (coordinates[11] - factors[1][2]) / factors[0][2];
651
652             /* Set the computed coordinates */
653             text.setCorners(coordinates);
654
655         } catch (DegenerateMatrixException e) {
656             // TODO Auto-generated catch block
657             e.printStackTrace();
658         }
659     }
660 }