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