Bug 9031 fixed: Misalignment when using xstring with a matrix
[scilab.git] / scilab / modules / scirenderer / src / org / scilab / forge / scirenderer / texture / BufferedImageTextureDrawingTools.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2009-2012 - 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.forge.scirenderer.texture;
13
14 import org.scilab.forge.scirenderer.implementation.jogl.utils.G2DShortCuts;
15 import org.scilab.forge.scirenderer.shapes.appearance.Appearance;
16 import org.scilab.forge.scirenderer.shapes.appearance.Color;
17
18 import javax.swing.Icon;
19 import javax.swing.JLabel;
20 import java.awt.AlphaComposite;
21 import java.awt.Dimension;
22 import java.awt.Graphics2D;
23 import java.awt.RenderingHints;
24 import java.awt.font.TextLayout;
25 import java.awt.geom.AffineTransform;
26 import java.awt.geom.Rectangle2D;
27
28 /**
29  *
30  * Implementation of {@link org.scilab.forge.scirenderer.texture.TextureDrawingTools}.
31  * This implementation create a {@link TextureBufferedImage} an fill it with texture drawing.
32  *
33  * @author Pierre Lando
34  */
35 public class BufferedImageTextureDrawingTools implements TextureDrawingTools {
36
37     /**
38      * The {@link Graphics2D} used to fill the {@link TextureBufferedImage}
39      */
40     private Graphics2D g2d;
41     private final TextureBufferedImage image;
42     private final Dimension textureSize;
43     private final AffineTransform baseTransform;
44
45     /**
46      * Default constructor.
47      * @param textureSize the texture size.
48      */
49     public BufferedImageTextureDrawingTools(Dimension textureSize) {
50         image = new TextureBufferedImage(textureSize.width, textureSize.height);
51         this.textureSize = textureSize;
52
53         double deltaW = (image.getWidth() - textureSize.width) / 2.0;
54         double deltaH = (image.getHeight() - textureSize.height) / 2.0;
55         baseTransform = AffineTransform.getTranslateInstance(deltaW, deltaH);
56     }
57
58     /**
59      * Ask this image to accept a texture drawer.
60      * This image will contain the drawing of the given drawer.
61      * @param textureDrawer the given texture drawer.
62      */
63     public void accept(TextureDrawer textureDrawer) {
64         g2d = image.createGraphics();
65         g2d.setComposite(AlphaComposite.Src);
66         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
67                              RenderingHints.VALUE_ANTIALIAS_ON);
68         g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
69                              RenderingHints.VALUE_RENDER_QUALITY);
70         g2d.transform(baseTransform);
71
72         // Change center coordinate to (0, 0).
73         if (textureDrawer.getOriginPosition() == TextureDrawer.OriginPosition.CENTER) {
74             g2d.translate(textureSize.width / 2, textureSize.height / 2);
75         }
76
77         textureDrawer.draw(this);
78
79         g2d.dispose();
80     }
81
82     @Override
83     public void drawPlus(int size, Appearance appearance) {
84         int r = size / 2;
85         int[] coords1 = new int[] { -r, 0, r, 0};
86         int[] coords2 = new int[] {0, -r, 0, r};
87
88         drawPolyline(coords1, appearance);
89         drawPolyline(coords2, appearance);
90     }
91
92     @Override
93     public void drawPolyline(int[] coordinates, Appearance appearance) {
94         int nbPoint = coordinates.length / 2;
95
96         int[] xCoordinates = new int[nbPoint];
97         int[] yCoordinates = new int[nbPoint];
98
99         int k = 0;
100         for (int i = 0; i < coordinates.length; i += 2) {
101             xCoordinates[k] = coordinates[i];
102             yCoordinates[k] = coordinates[i + 1];
103             k++;
104         }
105
106         G2DShortCuts.useLineAppearance(g2d, appearance);
107         G2DShortCuts.useColor(g2d, appearance.getLineColor());
108         g2d.drawPolyline(xCoordinates, yCoordinates, nbPoint);
109
110     }
111
112     @Override
113     public void fillPolygon(int[] coordinates, Appearance appearance) {
114         int nbPoint = coordinates.length / 2;
115
116         int[] xCoordinates = new int[nbPoint];
117         int[] yCoordinates = new int[nbPoint];
118
119         int k = 0;
120         for (int i = 0; i < coordinates.length; i += 2) {
121             xCoordinates[k] = coordinates[i];
122             yCoordinates[k] = coordinates[i + 1];
123             k++;
124         }
125
126         if (appearance.getFillColor().getAlphaAsFloat() != 0) {
127             G2DShortCuts.useColor(g2d, appearance.getFillColor());
128             g2d.fillPolygon(xCoordinates, yCoordinates, nbPoint);
129         }
130
131         if (!appearance.getLineColor().equals(appearance.getFillColor())) {
132             int usedLength = coordinates.length - (coordinates.length % 2);
133             int[] borderCoordinate = new int[usedLength + 2];
134             System.arraycopy(coordinates, 0, borderCoordinate, 0, usedLength);
135             borderCoordinate[usedLength]     = coordinates[0];
136             borderCoordinate[usedLength + 1] = coordinates[1];
137
138             drawPolyline(borderCoordinate, appearance);
139         }
140     }
141
142     @Override
143     public void drawCircle(int x, int y, int diameter, Appearance appearance) {
144         G2DShortCuts.useLineAppearance(g2d, appearance);
145         G2DShortCuts.useColor(g2d, appearance.getLineColor());
146         int r = diameter / 2;
147         g2d.drawOval(x - r, y - r, diameter, diameter);
148     }
149
150     @Override
151     public void fillDisc(int x, int y, int diameter, Color color) {
152         if (color.getAlphaAsFloat() != 0) {
153             G2DShortCuts.useColor(g2d, color);
154             int r = diameter / 2;
155             g2d.fillOval(x - r, y - r, diameter, diameter);
156         }
157     }
158
159     @Override
160     public void draw(TextEntity textEntity, int x, int y) {
161         if ((textEntity != null) && (textEntity.isValid())) {
162             if (textEntity.isTextAntiAliased()) {
163                 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
164             } else {
165                 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
166             }
167
168             if (textEntity.isTextUseFractionalMetrics()) {
169                 g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
170             } else {
171                 g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
172             }
173             g2d.setColor(textEntity.getTextColor());
174             TextLayout textLayout = new TextLayout(textEntity.getText(), textEntity.getFont(), g2d.getFontRenderContext());
175             Rectangle2D bounds = textLayout.getBounds();
176             textLayout.draw(g2d, (float) (x + 1 - bounds.getX()), (float) (y + textLayout.getAscent()));
177         }
178     }
179
180     @Override
181     public void draw(Icon icon, int x, int y) {
182         icon.paintIcon(new JLabel(), g2d, x, y);
183     }
184
185     @Override
186     public void clear(Color color) {
187         AffineTransform oldTransform = g2d.getTransform();
188         g2d.setTransform(baseTransform);
189         G2DShortCuts.useColor(g2d, color);
190         g2d.fillRect(0, 0, textureSize.width, textureSize.height);
191         g2d.setTransform(oldTransform);
192     }
193
194     /**
195      * Return the image.
196      * @return the image.
197      */
198     public TextureBufferedImage getImage() {
199         return image;
200     }
201 }