Bug 9031 fixed: Misalignment when using xstring with a matrix
[scilab.git] / scilab / modules / renderer / src / java / org / scilab / modules / renderer / JoGLView / util / TextObjectSpriteDrawer.java
index c407124..b4b0bd5 100644 (file)
@@ -14,11 +14,14 @@ package org.scilab.modules.renderer.JoGLView.util;
 
 import java.awt.Dimension;
 import java.awt.Font;
+import java.awt.font.TextLayout;
+import java.awt.geom.Rectangle2D;
 
 import javax.swing.Icon;
 
 import org.scilab.forge.jlatexmath.TeXConstants;
 import org.scilab.forge.jlatexmath.TeXFormula;
+import org.scilab.forge.jlatexmath.TeXIcon;
 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
 import org.scilab.forge.scirenderer.shapes.appearance.Color;
 import org.scilab.forge.scirenderer.texture.TextEntity;
@@ -40,16 +43,18 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
     /**
      * Scilab text margin.
      */
-    private static final int MARGIN = 2;
+    private static final int HMARGIN = 2;
+    private static final int VMARGIN = 2;
+    private static final int SPACEWIDTH = (int) Math.ceil(new TextEntity("_").getSize().getWidth()) - 2;
 
     private Appearance appearance;
     private int thickness;
     private final Object[][] entities;
     private float alignmentFactor;
-    private final int spaceWidth;
 
     private final int[] lineHeight;
     private final int[] columnWidth;
+    private final float[] lineAscent;
 
     private final int width;
     private final int height;
@@ -60,8 +65,6 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
      * @param textObject the scilab {@see Text} to draw.
      */
     public TextObjectSpriteDrawer(final ColorMap colorMap, final TextObject textObject) {
-        this.spaceWidth = computeSpaceWidth();
-
         String[][] stringArray = computeTextData(textObject);
         int columnNumber = -1;
         for (String[] stringLine : stringArray) {
@@ -70,6 +73,7 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
         int lineNumber = stringArray.length;
 
         this.lineHeight = new int[lineNumber];
+        this.lineAscent = new float[lineNumber];
         this.columnWidth = new int[columnNumber];
         this.entities = new Object[columnNumber][lineNumber];
 
@@ -79,8 +83,8 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
 
         fillEntityMatrix(stringArray, fractionalFont, textColor, font);
 
-        this.width  = sum(columnWidth) + MARGIN * (columnNumber + 1) + 2 * thickness + spaceWidth * (columnNumber - 1);
-        this.height = sum(lineHeight)  + MARGIN * (lineNumber + 1) + 2 * thickness;
+        this.width  = sum(columnWidth) + HMARGIN * (columnNumber + 1) + 2 * thickness + SPACEWIDTH * (columnNumber - 1);
+        this.height = sum(lineHeight)  + VMARGIN * (lineNumber + 1) + 2 * thickness;
     }
 
     /**
@@ -91,8 +95,6 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
      * @param scaleFactor the scale factor to apply.
      */
     public TextObjectSpriteDrawer(final ColorMap colorMap, final TextObject textObject, double scaleFactor) {
-        this.spaceWidth = computeSpaceWidth();
-
         String[][] stringArray = computeTextData(textObject);
         int columnNumber = -1;
         for (String[] stringLine : stringArray) {
@@ -101,6 +103,7 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
         int lineNumber = stringArray.length;
 
         this.lineHeight = new int[lineNumber];
+        this.lineAscent = new float[lineNumber];
         this.columnWidth = new int[columnNumber];
         this.entities = new Object[columnNumber][lineNumber];
 
@@ -111,8 +114,8 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
         /* Fill the entity matrix */
         fillEntityMatrix(stringArray, fractionalFont, textColor, font);
 
-        this.width  = (int)((double)sum(columnWidth) + scaleFactor * (double)(MARGIN * (columnNumber + 1)) + 2 * thickness + scaleFactor * (double)(spaceWidth * (columnNumber - 1)));
-        this.height = (int)((double)sum(lineHeight)  + scaleFactor * (double)(MARGIN * (lineNumber + 1)) + 2 * thickness);
+        this.width  = (int)((double)sum(columnWidth) + scaleFactor * (double)(HMARGIN * (columnNumber + 1)) + 2 * thickness + scaleFactor * (double)(SPACEWIDTH * (columnNumber - 1)));
+        this.height = (int)((double)sum(lineHeight)  + scaleFactor * (double)(VMARGIN * (lineNumber + 1)) + 2 * thickness);
     }
 
     /**
@@ -130,17 +133,21 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
                 if (text != null) {
                     Dimension dimension = null;
                     Icon icon = null;
+                    float ascent = 0;
                     if (isLatex(text)) {
                         LoadClassPath.loadOnUse("graphics_latex_textrendering");
                         try {
                             TeXFormula formula = new TeXFormula(text.substring(1, text.length() - 1));
                             formula.setColor(textColor);
                             icon = formula.createTeXIcon(TeXConstants.STYLE_DISPLAY, font.getSize());
+                            ascent = ((TeXIcon) icon).getIconHeight() - ((TeXIcon) icon).getIconDepth();
                         } catch (Exception e) { }
                     } else if (isMathML(text)) {
                         LoadClassPath.loadOnUse("graphics_mathml_textrendering");
                         try {
                             icon = ScilabSpecialTextUtilities.compileMathMLExpression(text, font.getSize(), textColor);
+                            ScilabSpecialTextUtilities.SpecialIcon si = (ScilabSpecialTextUtilities.SpecialIcon) icon;
+                            ascent = si.getIconHeight() - si.getIconDepth();
                         } catch (Exception e) { }
                     }
 
@@ -155,8 +162,11 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
                         textEntity.setFont(font);
                         entities[column][line] = textEntity;
                         dimension = textEntity.getSize();
+                        ascent = textEntity.getLayout().getAscent();
                     }
 
+                    lineAscent[line] = Math.max(lineAscent[line], ascent);
+
                     if (dimension != null) {
                         columnWidth[column] = Math.max(columnWidth[column], dimension.width);
                         lineHeight[line] = Math.max(lineHeight[line], dimension.height);
@@ -193,33 +203,44 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
             drawingTools.clear(appearance.getFillColor());
         }
 
-        int currentMargin = getMargin();
-        int currentSpaceWidth = getSpaceWidth();
+        final int currentHMargin = getHMargin();
+        final int currentVMargin = getVMargin();
+        final int currentSpaceWidth = getSpaceWidth();
 
         // Draw text.
-        int x = currentMargin + thickness;
+        int x = currentHMargin + thickness;
         int column = 0;
         for (Object[] entitiesLine : entities) {
-            int y = currentMargin + thickness;
+            int y = currentVMargin + thickness;
             int line = 0;
             for (Object entity : entitiesLine) {
                 if (entity != null) {
                     if (entity instanceof TextEntity) {
                         TextEntity textEntity = (TextEntity) entity;
+                        TextLayout layout = textEntity.getLayout();
                         double deltaX = alignmentFactor * (columnWidth[column] - textEntity.getSize().getWidth());
-                        drawingTools.draw(textEntity, (int) (x + deltaX), y);
-                        y += lineHeight[line] + currentMargin;
+                        drawingTools.draw(textEntity, (int) (x + deltaX), Math.round(y - layout.getAscent() + lineAscent[line]));
+                        y += lineHeight[line] + currentVMargin;
                         line++;
                     } else if (entity instanceof Icon) {
                         Icon icon = (Icon) entity;
                         double deltaX = alignmentFactor * (columnWidth[column] - icon.getIconWidth());
-                        drawingTools.draw(icon, (int) (x + deltaX), y);
-                        y += lineHeight[line] + currentMargin;
+                        if (icon instanceof TeXIcon) {
+                            TeXIcon tex = (TeXIcon) icon;
+                            float ascent = tex.getIconHeight() - tex.getIconDepth();
+                            drawingTools.draw(icon, (int) (x + deltaX), Math.round(y - ascent + lineAscent[line]));
+                        } else {
+                            // MathML
+                            ScilabSpecialTextUtilities.SpecialIcon si = (ScilabSpecialTextUtilities.SpecialIcon) icon;
+                            int ascent = si.getIconHeight() - si.getIconDepth();
+                            drawingTools.draw(icon, (int) (x + deltaX), y - ascent + Math.round(lineAscent[line]));
+                        }
+                        y += lineHeight[line] + currentVMargin;
                         line++;
                     }
                 }
             }
-            x += columnWidth[column] + currentMargin + currentSpaceWidth;
+            x += columnWidth[column] + currentHMargin + currentSpaceWidth;
             column++;
         }
 
@@ -272,12 +293,16 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
         this.thickness = thickness;
     }
 
-    public int getMargin() {
-        return MARGIN;
+    public int getHMargin() {
+        return HMARGIN;
+    }
+
+    public int getVMargin() {
+        return VMARGIN;
     }
 
     public int getSpaceWidth() {
-        return spaceWidth;
+        return SPACEWIDTH;
     }
 
     /**
@@ -316,7 +341,7 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
      * @return the {@see Font} adapted to the given Scilab text.
      */
     private Font computeFont(final TextObject text, double scaleFactor) {
-        Font font  = FontManager.getSciFontManager().getFontFromIndex(text.getFontStyle(), 1.0);
+        Font font = FontManager.getSciFontManager().getFontFromIndex(text.getFontStyle(), 1.0);
         return font.deriveFont(font.getSize2D() * (float)scaleFactor);
     }
 
@@ -339,15 +364,6 @@ public class TextObjectSpriteDrawer implements TextureDrawer {
     }
 
     /**
-     * Compute and return the width of the space character.
-     * @return the width of the space character.
-     */
-    private int computeSpaceWidth() {
-        TextEntity spaceText = new TextEntity("_");
-        return (int) Math.ceil(spaceText.getSize().getWidth());
-    }
-
-    /**
      * Util function.
      * Return sum of the element of the given array.
      * @param values the given array.