| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /** |
| * @author Alexey A. Petrenko |
| * @version $Revision$ |
| */ |
| package org.apache.harmony.awt.gl; |
| |
| |
| import java.awt.AlphaComposite; |
| import java.awt.BasicStroke; |
| import java.awt.Color; |
| import java.awt.Composite; |
| import java.awt.Font; |
| import java.awt.FontMetrics; |
| import java.awt.Graphics2D; |
| import java.awt.Image; |
| import java.awt.Paint; |
| import java.awt.PaintContext; |
| import java.awt.Point; |
| import java.awt.Polygon; |
| import java.awt.Rectangle; |
| import java.awt.RenderingHints; |
| import java.awt.Shape; |
| import java.awt.Stroke; |
| import java.awt.Toolkit; |
| import java.awt.font.FontRenderContext; |
| import java.awt.font.GlyphVector; |
| import java.awt.image.AffineTransformOp; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.BufferedImageOp; |
| import java.awt.image.Raster; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.WritableRaster; |
| import java.awt.image.renderable.RenderableImage; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.Arc2D; |
| import java.awt.geom.Ellipse2D; |
| import java.awt.geom.Line2D; |
| import java.awt.geom.PathIterator; |
| import java.awt.geom.RoundRectangle2D; |
| import java.text.AttributedCharacterIterator; |
| import java.util.Map; |
| |
| import org.apache.harmony.awt.gl.Surface; |
| import org.apache.harmony.awt.gl.image.OffscreenImage; |
| import org.apache.harmony.awt.gl.render.Blitter; |
| import org.apache.harmony.awt.gl.render.JavaArcRasterizer; |
| import org.apache.harmony.awt.gl.render.JavaLineRasterizer; |
| import org.apache.harmony.awt.gl.render.JavaShapeRasterizer; |
| import org.apache.harmony.awt.gl.render.JavaTextRenderer; |
| import org.apache.harmony.awt.gl.render.NullBlitter; |
| |
| /* |
| * List of abstract methods to implement in subclusses |
| * Graphics.copyArea(int x, int y, int width, int height, int dx, int dy) |
| * Graphics.create() |
| * Graphics2D.getDeviceConfiguration() |
| * CommonGraphics2D.fillMultiRectAreaColor(MultiRectArea mra); |
| * CommonGraphics2D.fillMultiRectAreaPaint(MultiRectArea mra); |
| */ |
| |
| /** |
| * CommonGraphics2D class is a super class for all system-dependent |
| * implementations. It implements major part of Graphics and Graphics2D |
| * abstract methods. |
| * <h2>CommonGraphics2D Class Internals</h2> |
| * <h3>Line and Shape Rasterizers</h3> |
| * <p> |
| * The CommonGraphics2D class splits all shapes into a set of rectangles |
| * to unify the drawing process for different operating systems and architectures. |
| * For this purpose Java 2D* uses the JavaShapeRasterizer and the JavaLineRasterizer |
| * classes from the org.apache.harmony.awt.gl.render package. The JavaShapeRasterizer |
| * class splits an object implementing a Shape interface into a set of rectangles and |
| * produces a MultiRectArea object. The JavaLineRasterizer class makes line drawing |
| * more accurate and processes lines with strokes, which are instances of the BasicStroke |
| * class. |
| * </p> |
| * <p> |
| * To port the shape drawing to another platform you just need to override |
| * rectangle-drawing methods. However, if your operating system has functions to draw |
| * particular shapes, you can optimize your subclass of the CommonGraphics2D class by |
| * using this functionality in overridden methods. |
| * </p> |
| |
| * <h3>Blitters</h3> |
| * <p> |
| * Blitter classes draw images on the display or buffered images. All blitters inherit |
| * the org.apache.harmony.awt.gl.render.Blitter interface. |
| * </p> |
| * <p>Blitters are divided into: |
| * <ul> |
| * <li>Native blitters for simple types of images, which the underlying native library |
| * can draw.</li> |
| * <li>Java* blitters for those types of images, which the underlying native library |
| * cannot handle.</li> |
| * </ul></p> |
| * <p> |
| * DRL Java 2D* also uses blitters to fill the shapes and the user-defined subclasses |
| * of the java.awt.Paint class with paints, which the system does not support. |
| * </p> |
| * |
| *<h3>Text Renderers</h3> |
| *<p> |
| *Text renderers draw strings and glyph vectors. All text renderers are subclasses |
| *of the org.apache.harmony.awt.gl.TextRenderer class. |
| *</p> |
| * |
| */ |
| public abstract class CommonGraphics2D extends Graphics2D { |
| protected Surface dstSurf = null; |
| protected Blitter blitter = NullBlitter.getInstance(); |
| protected RenderingHints hints = new RenderingHints(null); |
| |
| // Clipping things |
| protected MultiRectArea clip = null; |
| |
| protected Paint paint = Color.WHITE; |
| protected Color fgColor = Color.WHITE; |
| protected Color bgColor = Color.BLACK; |
| |
| protected Composite composite = AlphaComposite.SrcOver; |
| |
| protected Stroke stroke = new BasicStroke(); |
| |
| //TODO: Think more about FontRenderContext |
| protected FontRenderContext frc = new FontRenderContext(null, false, false); |
| |
| protected JavaShapeRasterizer jsr = new JavaShapeRasterizer(); |
| |
| protected Font font = new Font("Dialog", Font.PLAIN, 12);; //$NON-NLS-1$ |
| |
| protected TextRenderer jtr = JavaTextRenderer.inst; |
| |
| // Current graphics transform |
| protected AffineTransform transform = new AffineTransform(); |
| protected double[] matrix = new double[6]; |
| |
| // Original user->device translation as transform and point |
| //public AffineTransform origTransform = new AffineTransform(); |
| public Point origPoint = new Point(0, 0); |
| |
| |
| // Print debug output or not |
| protected static final boolean debugOutput = "1".equals(System.getProperty("g2d.debug")); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| // Constructors |
| protected CommonGraphics2D() { |
| } |
| |
| protected CommonGraphics2D(int tx, int ty) { |
| this(tx, ty, null); |
| } |
| |
| protected CommonGraphics2D(int tx, int ty, MultiRectArea clip) { |
| setTransform(AffineTransform.getTranslateInstance(tx, ty)); |
| //origTransform = AffineTransform.getTranslateInstance(tx, ty); |
| origPoint = new Point(tx, ty); |
| setClip(clip); |
| } |
| |
| // Public methods |
| @Override |
| public void addRenderingHints(Map<?,?> hints) { |
| this.hints.putAll(hints); |
| } |
| |
| @Override |
| public void clearRect(int x, int y, int width, int height) { |
| Color c = getColor(); |
| Paint p = getPaint(); |
| setColor(getBackground()); |
| fillRect(x, y, width, height); |
| setColor(c); |
| setPaint(p); |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.clearRect("+x+", "+y+", "+width+", "+height+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| } |
| } |
| |
| @Override |
| public void clipRect(int x, int y, int width, int height) { |
| clip(new Rectangle(x, y, width, height)); |
| } |
| |
| |
| @Override |
| public void clip(Shape s) { |
| if (s == null) { |
| clip = null; |
| return; |
| } |
| |
| MultiRectArea mra = null; |
| if (s instanceof MultiRectArea) { |
| mra = new MultiRectArea((MultiRectArea)s); |
| mra.translate((int)transform.getTranslateX(), (int)transform.getTranslateY()); |
| } else { |
| int type = transform.getType(); |
| if(s instanceof Rectangle && (type & (AffineTransform.TYPE_IDENTITY | |
| AffineTransform.TYPE_TRANSLATION)) != 0){ |
| mra = new MultiRectArea((Rectangle)s); |
| if(type == AffineTransform.TYPE_TRANSLATION){ |
| mra.translate((int)transform.getTranslateX(), (int)transform.getTranslateY()); |
| } |
| } else { |
| s = transform.createTransformedShape(s); |
| mra = jsr.rasterize(s, 0.5); |
| } |
| } |
| |
| if (clip == null) { |
| setTransformedClip(mra); |
| } else { |
| clip.intersect(mra); |
| setTransformedClip(clip); |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| // Do nothing for Java only classes |
| } |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * Draw methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public void draw(Shape s) { |
| if (stroke instanceof BasicStroke && ((BasicStroke)stroke).getLineWidth() <= 1) { |
| //TODO: Think about drawing the shape in one fillMultiRectArea call |
| BasicStroke bstroke = (BasicStroke)stroke; |
| JavaLineRasterizer.LineDasher ld = (bstroke.getDashArray() == null)?null:new JavaLineRasterizer.LineDasher(bstroke.getDashArray(), bstroke.getDashPhase()); |
| PathIterator pi = s.getPathIterator(transform, 0.5); |
| float []points = new float[6]; |
| int x1 = Integer.MIN_VALUE; |
| int y1 = Integer.MIN_VALUE; |
| int cx1 = Integer.MIN_VALUE; |
| int cy1 = Integer.MIN_VALUE; |
| while (!pi.isDone()) { |
| switch (pi.currentSegment(points)) { |
| case PathIterator.SEG_MOVETO: |
| x1 = (int)Math.floor(points[0]); |
| y1 = (int)Math.floor(points[1]); |
| cx1 = x1; |
| cy1 = y1; |
| break; |
| case PathIterator.SEG_LINETO: |
| int x2 = (int)Math.floor(points[0]); |
| int y2 = (int)Math.floor(points[1]); |
| fillMultiRectArea(JavaLineRasterizer.rasterize(x1, y1, x2, y2, null, ld, false)); |
| x1 = x2; |
| y1 = y2; |
| break; |
| case PathIterator.SEG_CLOSE: |
| x2 = cx1; |
| y2 = cy1; |
| fillMultiRectArea(JavaLineRasterizer.rasterize(x1, y1, x2, y2, null, ld, false)); |
| x1 = x2; |
| y1 = y2; |
| break; |
| } |
| pi.next(); |
| } |
| } else { |
| s = stroke.createStrokedShape(s); |
| s = transform.createTransformedShape(s); |
| fillMultiRectArea(jsr.rasterize(s, 0.5)); |
| } |
| } |
| |
| @Override |
| public void drawArc(int x, int y, int width, int height, int sa, int ea) { |
| if (stroke instanceof BasicStroke && ((BasicStroke)stroke).getLineWidth() <= 1 && |
| ((BasicStroke)stroke).getDashArray() == null && |
| (transform.isIdentity() || transform.getType() == AffineTransform.TYPE_TRANSLATION)) { |
| Point p = new Point(x, y); |
| transform.transform(p, p); |
| MultiRectArea mra = JavaArcRasterizer.rasterize(x, y, width, height, sa, ea, clip); |
| fillMultiRectArea(mra); |
| return; |
| } |
| draw(new Arc2D.Float(x, y, width, height, sa, ea, Arc2D.OPEN)); |
| } |
| |
| |
| @Override |
| public boolean drawImage(Image image, int x, int y, Color bgcolor, |
| ImageObserver imageObserver) { |
| |
| if(image == null) { |
| return true; |
| } |
| |
| boolean done = false; |
| boolean somebits = false; |
| Surface srcSurf = null; |
| if(image instanceof OffscreenImage){ |
| OffscreenImage oi = (OffscreenImage) image; |
| if((oi.getState() & ImageObserver.ERROR) != 0) { |
| return false; |
| } |
| done = oi.prepareImage(imageObserver); |
| somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0; |
| srcSurf = oi.getImageSurface(); |
| }else{ |
| done = true; |
| srcSurf = Surface.getImageSurface(image); |
| } |
| |
| if(done || somebits) { |
| int w = srcSurf.getWidth(); |
| int h = srcSurf.getHeight(); |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, (AffineTransform) transform.clone(), |
| composite, bgcolor, clip); |
| } |
| return done; |
| } |
| |
| @Override |
| public boolean drawImage(Image image, int x, int y, ImageObserver imageObserver) { |
| return drawImage(image, x, y, null, imageObserver); |
| } |
| |
| @Override |
| public boolean drawImage(Image image, int x, int y, int width, int height, |
| Color bgcolor, ImageObserver imageObserver) { |
| |
| if(image == null) { |
| return true; |
| } |
| if(width == 0 || height == 0) { |
| return true; |
| } |
| |
| boolean done = false; |
| boolean somebits = false; |
| Surface srcSurf = null; |
| |
| if(image instanceof OffscreenImage){ |
| OffscreenImage oi = (OffscreenImage) image; |
| if((oi.getState() & ImageObserver.ERROR) != 0) { |
| return false; |
| } |
| done = oi.prepareImage(imageObserver); |
| somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0; |
| srcSurf = oi.getImageSurface(); |
| }else{ |
| done = true; |
| srcSurf = Surface.getImageSurface(image); |
| } |
| |
| if(done || somebits) { |
| int w = srcSurf.getWidth(); |
| int h = srcSurf.getHeight(); |
| if(w == width && h == height){ |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, |
| (AffineTransform) transform.clone(), |
| composite, bgcolor, clip); |
| }else{ |
| AffineTransform xform = new AffineTransform(); |
| xform.setToScale((float)width / w, (float)height / h); |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, |
| (AffineTransform) transform.clone(), |
| xform, composite, bgcolor, clip); |
| } |
| } |
| return done; |
| } |
| |
| @Override |
| public boolean drawImage(Image image, int x, int y, int width, int height, |
| ImageObserver imageObserver) { |
| return drawImage(image, x, y, width, height, null, imageObserver); |
| } |
| |
| @Override |
| public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, |
| int sx1, int sy1, int sx2, int sy2, Color bgcolor, |
| ImageObserver imageObserver) { |
| |
| if(image == null) { |
| return true; |
| } |
| if(dx1 == dx2 || dy1 == dy2 || sx1 == sx2 || sy1 == sy2) { |
| return true; |
| } |
| |
| boolean done = false; |
| boolean somebits = false; |
| Surface srcSurf = null; |
| if(image instanceof OffscreenImage){ |
| OffscreenImage oi = (OffscreenImage) image; |
| if((oi.getState() & ImageObserver.ERROR) != 0) { |
| return false; |
| } |
| done = oi.prepareImage(imageObserver); |
| somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0; |
| srcSurf = oi.getImageSurface(); |
| }else{ |
| done = true; |
| srcSurf = Surface.getImageSurface(image); |
| } |
| |
| if(done || somebits) { |
| |
| int dstX = dx1; |
| int dstY = dy1; |
| int srcX = sx1; |
| int srcY = sy1; |
| |
| int dstW = dx2 - dx1; |
| int dstH = dy2 - dy1; |
| int srcW = sx2 - sx1; |
| int srcH = sy2 - sy1; |
| |
| if(srcW == dstW && srcH == dstH){ |
| blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf, srcW, srcH, |
| (AffineTransform) transform.clone(), |
| composite, bgcolor, clip); |
| }else{ |
| AffineTransform xform = new AffineTransform(); |
| xform.setToScale((float)dstW / srcW, (float)dstH / srcH); |
| blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf, srcW, srcH, |
| (AffineTransform) transform.clone(), |
| xform, composite, bgcolor, clip); |
| } |
| } |
| return done; |
| } |
| |
| @Override |
| public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, |
| int sx1, int sy1, int sx2, int sy2, ImageObserver imageObserver) { |
| |
| return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, |
| imageObserver); |
| } |
| |
| @Override |
| public void drawImage(BufferedImage bufImage, BufferedImageOp op, |
| int x, int y) { |
| |
| if(bufImage == null) { |
| return; |
| } |
| |
| if(op == null) { |
| drawImage(bufImage, x, y, null); |
| } else if(op instanceof AffineTransformOp){ |
| AffineTransformOp atop = (AffineTransformOp) op; |
| AffineTransform xform = atop.getTransform(); |
| Surface srcSurf = Surface.getImageSurface(bufImage); |
| int w = srcSurf.getWidth(); |
| int h = srcSurf.getHeight(); |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, |
| (AffineTransform) transform.clone(), xform, |
| composite, null, clip); |
| } else { |
| bufImage = op.filter(bufImage, null); |
| Surface srcSurf = Surface.getImageSurface(bufImage); |
| int w = srcSurf.getWidth(); |
| int h = srcSurf.getHeight(); |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, |
| (AffineTransform) transform.clone(), |
| composite, null, clip); |
| } |
| } |
| |
| @Override |
| public boolean drawImage(Image image, AffineTransform trans, |
| ImageObserver imageObserver) { |
| |
| if(image == null) { |
| return true; |
| } |
| if(trans == null || trans.isIdentity()) { |
| return drawImage(image, 0, 0, imageObserver); |
| } |
| |
| boolean done = false; |
| boolean somebits = false; |
| Surface srcSurf = null; |
| if(image instanceof OffscreenImage){ |
| OffscreenImage oi = (OffscreenImage) image; |
| if((oi.getState() & ImageObserver.ERROR) != 0) { |
| return false; |
| } |
| done = oi.prepareImage(imageObserver); |
| somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0; |
| srcSurf = oi.getImageSurface(); |
| }else{ |
| done = true; |
| srcSurf = Surface.getImageSurface(image); |
| } |
| |
| if(done || somebits) { |
| int w = srcSurf.getWidth(); |
| int h = srcSurf.getHeight(); |
| AffineTransform xform = (AffineTransform) transform.clone(); |
| xform.concatenate(trans); |
| blitter.blit(0, 0, srcSurf, 0, 0, dstSurf, w, h, xform, composite, |
| null, clip); |
| } |
| return done; |
| } |
| |
| @Override |
| public void drawLine(int x1, int y1, int x2, int y2) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.drawLine("+x1+", "+y1+", "+x2+", "+y2+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| } |
| |
| if (stroke instanceof BasicStroke && ((BasicStroke)stroke).getLineWidth() <= 1) { |
| BasicStroke bstroke = (BasicStroke)stroke; |
| Point p1 = new Point(x1, y1); |
| Point p2 = new Point(x2, y2); |
| transform.transform(p1, p1); |
| transform.transform(p2, p2); |
| JavaLineRasterizer.LineDasher ld = (bstroke.getDashArray() == null)?null:new JavaLineRasterizer.LineDasher(bstroke.getDashArray(), bstroke.getDashPhase()); |
| MultiRectArea mra = JavaLineRasterizer.rasterize(p1.x, p1.y, p2.x, p2.y, null, ld, false); |
| fillMultiRectArea(mra); |
| return; |
| } |
| draw(new Line2D.Float(x1, y1, x2, y2)); |
| } |
| |
| @Override |
| public void drawOval(int x, int y, int width, int height) { |
| if (stroke instanceof BasicStroke && ((BasicStroke)stroke).getLineWidth() <= 1 && |
| ((BasicStroke)stroke).getDashArray() == null && |
| (transform.isIdentity() || transform.getType() == AffineTransform.TYPE_TRANSLATION)) { |
| Point p = new Point(x, y); |
| transform.transform(p, p); |
| MultiRectArea mra = JavaArcRasterizer.rasterize(x, y, width, height, 0, 360, clip); |
| fillMultiRectArea(mra); |
| return; |
| } |
| draw(new Ellipse2D.Float(x, y, width, height)); |
| } |
| |
| @Override |
| public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) { |
| draw(new Polygon(xpoints, ypoints, npoints)); |
| } |
| |
| @Override |
| public void drawPolygon(Polygon polygon) { |
| draw(polygon); |
| } |
| |
| @Override |
| public void drawPolyline(int[] xpoints, int[] ypoints, int npoints) { |
| for (int i = 0; i < npoints-1; i++) { |
| drawLine(xpoints[i], ypoints[i], xpoints[i+1], ypoints[i+1]); |
| } |
| } |
| |
| @Override |
| public void drawRenderableImage(RenderableImage img, AffineTransform xform) { |
| if (img == null) { |
| return; |
| } |
| |
| double scaleX = xform.getScaleX(); |
| double scaleY = xform.getScaleY(); |
| if (scaleX == 1 && scaleY == 1) { |
| drawRenderedImage(img.createDefaultRendering(), xform); |
| } else { |
| int width = (int)Math.round(img.getWidth()*scaleX); |
| int height = (int)Math.round(img.getHeight()*scaleY); |
| xform = (AffineTransform)xform.clone(); |
| xform.scale(1, 1); |
| drawRenderedImage(img.createScaledRendering(width, height, null), xform); |
| } |
| } |
| |
| @Override |
| public void drawRenderedImage(RenderedImage rimg, AffineTransform xform) { |
| if (rimg == null) { |
| return; |
| } |
| |
| Image img = null; |
| |
| if (rimg instanceof Image) { |
| img = (Image)rimg; |
| } else { |
| //TODO: Create new class to provide Image interface for RenderedImage or rewrite this method |
| img = new BufferedImage(rimg.getColorModel(), rimg.copyData(null), false, null); |
| } |
| |
| drawImage(img, xform, null); |
| } |
| |
| @Override |
| public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.drawRoundRect("+x+", "+y+", "+width+", "+height+","+arcWidth+", "+arcHeight+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ |
| } |
| |
| draw(new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight)); |
| } |
| |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * String methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public void drawString(AttributedCharacterIterator iterator, float x, float y) { |
| GlyphVector gv = font.createGlyphVector(frc, iterator); |
| drawGlyphVector(gv, x, y); |
| } |
| |
| @Override |
| public void drawString(AttributedCharacterIterator iterator, int x, int y) { |
| drawString(iterator, (float)x, (float)y); |
| } |
| |
| @Override |
| public void drawString(String str, int x, int y) { |
| drawString(str, (float)x, (float)y); |
| } |
| |
| @Override |
| public void drawString(String str, float x, float y) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.drawString("+str+", "+x+", "+y+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| } |
| |
| AffineTransform at = (AffineTransform)this.getTransform().clone(); |
| AffineTransform fontTransform = font.getTransform(); |
| at.concatenate(fontTransform); |
| |
| double[] matrix = new double[6]; |
| if (!at.isIdentity()){ |
| |
| int atType = at.getType(); |
| at.getMatrix(matrix); |
| |
| // TYPE_TRANSLATION |
| if (atType == AffineTransform.TYPE_TRANSLATION){ |
| jtr.drawString(this, str, |
| (float)(x+fontTransform.getTranslateX()), |
| (float)(y+fontTransform.getTranslateY())); |
| return; |
| } |
| // TODO: we use slow type of drawing strings when Font object |
| // in Graphics has transforms, we just fill outlines. New textrenderer |
| // is to be implemented. |
| Shape sh = font.createGlyphVector(this.getFontRenderContext(), str).getOutline(x, y); |
| this.fill(sh); |
| |
| } else { |
| jtr.drawString(this, str, x, y); |
| } |
| |
| } |
| |
| @Override |
| public void drawGlyphVector(GlyphVector gv, float x, float y) { |
| |
| AffineTransform at = gv.getFont().getTransform(); |
| |
| double[] matrix = new double[6]; |
| if ((at != null) && (!at.isIdentity())){ |
| |
| int atType = at.getType(); |
| at.getMatrix(matrix); |
| |
| // TYPE_TRANSLATION |
| if ((atType == AffineTransform.TYPE_TRANSLATION) && |
| ((gv.getLayoutFlags() & GlyphVector.FLAG_HAS_TRANSFORMS) == 0)){ |
| jtr.drawGlyphVector(this, gv, (int)(x+matrix[4]), (int)(y+matrix[5])); |
| return; |
| } |
| } else { |
| if (((gv.getLayoutFlags() & GlyphVector.FLAG_HAS_TRANSFORMS) == 0)){ |
| jtr.drawGlyphVector(this, gv, x, y); |
| return; |
| } |
| } |
| |
| // TODO: we use slow type of drawing strings when Font object |
| // in Graphics has transforms, we just fill outlines. New textrenderer |
| // is to be implemented. |
| |
| Shape sh = gv.getOutline(x, y); |
| this.fill(sh); |
| |
| } |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * Fill methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public void fill(Shape s) { |
| s = transform.createTransformedShape(s); |
| MultiRectArea mra = jsr.rasterize(s, 0.5); |
| fillMultiRectArea(mra); |
| } |
| |
| @Override |
| public void fillArc(int x, int y, int width, int height, int sa, int ea) { |
| fill(new Arc2D.Float(x, y, width, height, sa, ea, Arc2D.PIE)); |
| } |
| |
| @Override |
| public void fillOval(int x, int y, int width, int height) { |
| fill(new Ellipse2D.Float(x, y, width, height)); |
| } |
| |
| @Override |
| public void fillPolygon(int[] xpoints, int[] ypoints, int npoints) { |
| fill(new Polygon(xpoints, ypoints, npoints)); |
| } |
| |
| @Override |
| public void fillPolygon(Polygon polygon) { |
| fill(polygon); |
| } |
| |
| @Override |
| public void fillRect(int x, int y, int width, int height) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.fillRect("+x+", "+y+", "+width+", "+height+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| } |
| |
| fill(new Rectangle(x, y, width, height)); |
| } |
| |
| @Override |
| public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.fillRoundRect("+x+", "+y+", "+width+", "+height+","+arcWidth+", "+arcHeight+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ |
| } |
| |
| fill(new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight)); |
| } |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * Get methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public Color getBackground() { |
| return bgColor; |
| } |
| |
| @Override |
| public Shape getClip() { |
| if (clip == null) { |
| return null; |
| } |
| |
| MultiRectArea res = new MultiRectArea(clip); |
| res.translate(-Math.round((float)transform.getTranslateX()), -Math.round((float)transform.getTranslateY())); |
| return res; |
| } |
| |
| @Override |
| public Rectangle getClipBounds() { |
| if (clip == null) { |
| return null; |
| } |
| |
| Rectangle res = (Rectangle) clip.getBounds().clone(); |
| res.translate(-Math.round((float)transform.getTranslateX()), -Math.round((float)transform.getTranslateY())); |
| return res; |
| } |
| |
| @Override |
| public Color getColor() { |
| return fgColor; |
| } |
| |
| @Override |
| public Composite getComposite() { |
| return composite; |
| } |
| |
| @Override |
| public Font getFont() { |
| return font; |
| } |
| |
| @SuppressWarnings("deprecation") |
| @Override |
| public FontMetrics getFontMetrics(Font font) { |
| return Toolkit.getDefaultToolkit().getFontMetrics(font); |
| } |
| |
| @Override |
| public FontRenderContext getFontRenderContext() { |
| return frc; |
| } |
| |
| @Override |
| public Paint getPaint() { |
| return paint; |
| } |
| |
| @Override |
| public Object getRenderingHint(RenderingHints.Key key) { |
| return hints.get(key); |
| } |
| |
| @Override |
| public RenderingHints getRenderingHints() { |
| return hints; |
| } |
| |
| @Override |
| public Stroke getStroke() { |
| return stroke; |
| } |
| |
| @Override |
| public AffineTransform getTransform() { |
| return (AffineTransform)transform.clone(); |
| } |
| |
| @Override |
| public boolean hit(Rectangle rect, Shape s, boolean onStroke) { |
| //TODO: Implement method.... |
| return false; |
| } |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * Transformation methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public void rotate(double theta) { |
| transform.rotate(theta); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void rotate(double theta, double x, double y) { |
| transform.rotate(theta, x, y); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void scale(double sx, double sy) { |
| transform.scale(sx, sy); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void shear(double shx, double shy) { |
| transform.shear(shx, shy); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void transform(AffineTransform at) { |
| transform.concatenate(at); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void translate(double tx, double ty) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.translate("+tx+", "+ty+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| transform.translate(tx, ty); |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void translate(int tx, int ty) { |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.translate("+tx+", "+ty+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| |
| transform.translate(tx, ty); |
| transform.getMatrix(matrix); |
| } |
| |
| |
| |
| |
| /*************************************************************************** |
| * |
| * Set methods |
| * |
| ***************************************************************************/ |
| |
| @Override |
| public void setBackground(Color color) { |
| bgColor = color; |
| } |
| |
| @Override |
| public void setClip(int x, int y, int width, int height) { |
| setClip(new Rectangle(x, y, width, height)); |
| } |
| |
| @Override |
| public void setClip(Shape s) { |
| if (s == null) { |
| setTransformedClip(null); |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.setClip(null)"); //$NON-NLS-1$ |
| } |
| return; |
| } |
| |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.setClip("+s.getBounds()+")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| if (s instanceof MultiRectArea) { |
| MultiRectArea nclip = new MultiRectArea((MultiRectArea)s); |
| nclip.translate(Math.round((float)transform.getTranslateX()), Math.round((float)transform.getTranslateY())); |
| setTransformedClip(nclip); |
| } else { |
| int type = transform.getType(); |
| if(s instanceof Rectangle && (type & (AffineTransform.TYPE_IDENTITY | |
| AffineTransform.TYPE_TRANSLATION)) != 0){ |
| MultiRectArea nclip = new MultiRectArea((Rectangle)s); |
| if(type == AffineTransform.TYPE_TRANSLATION){ |
| nclip.translate((int)transform.getTranslateX(), (int)transform.getTranslateY()); |
| } |
| setTransformedClip(nclip); |
| } else { |
| s = transform.createTransformedShape(s); |
| setTransformedClip(jsr.rasterize(s, 0.5)); |
| } |
| } |
| } |
| |
| @Override |
| public void setColor(Color color) { |
| if (color != null) { |
| fgColor = color; |
| paint = color; |
| } |
| } |
| |
| @Override |
| public void setComposite(Composite composite) { |
| this.composite = composite; |
| } |
| |
| @Override |
| public void setFont(Font font) { |
| this.font = font; |
| } |
| |
| @Override |
| public void setPaint(Paint paint) { |
| if (paint == null) |
| return; |
| |
| this.paint = paint; |
| if (paint instanceof Color) { |
| fgColor = (Color)paint; |
| } |
| } |
| |
| @Override |
| public void setPaintMode() { |
| composite = AlphaComposite.SrcOver; |
| } |
| |
| @Override |
| public void setRenderingHint(RenderingHints.Key key, Object value) { |
| hints.put(key, value); |
| } |
| |
| @Override |
| public void setRenderingHints(Map<?,?> hints) { |
| this.hints.clear(); |
| this.hints.putAll(hints); |
| } |
| |
| @Override |
| public void setStroke(Stroke stroke) { |
| this.stroke = stroke; |
| } |
| |
| @Override |
| public void setTransform(AffineTransform transform) { |
| this.transform = transform; |
| |
| transform.getMatrix(matrix); |
| } |
| |
| @Override |
| public void setXORMode(Color color) { |
| composite = new XORComposite(color); |
| } |
| |
| |
| // Protected methods |
| protected void setTransformedClip(MultiRectArea clip) { |
| this.clip = clip; |
| } |
| |
| /** |
| * This method fills the given MultiRectArea with current paint. |
| * It calls fillMultiRectAreaColor and fillMultiRectAreaPaint |
| * methods depending on the type of current paint. |
| * @param mra MultiRectArea to fill |
| */ |
| protected void fillMultiRectArea(MultiRectArea mra) { |
| if (clip != null) { |
| mra.intersect(clip); |
| } |
| |
| // Return if all stuff is clipped |
| if (mra.rect[0] < 5) { |
| return; |
| } |
| |
| if (debugOutput) { |
| System.err.println("CommonGraphics2D.fillMultiRectArea("+mra+")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| if (paint instanceof Color){ |
| fillMultiRectAreaColor(mra); |
| }else{ |
| fillMultiRectAreaPaint(mra); |
| } |
| } |
| |
| /** |
| * This method fills the given MultiRectArea with solid color. |
| * @param mra MultiRectArea to fill |
| */ |
| protected void fillMultiRectAreaColor(MultiRectArea mra) { |
| fillMultiRectAreaPaint(mra); |
| } |
| |
| /** |
| * This method fills the given MultiRectArea with any paint. |
| * @param mra MultiRectArea to fill |
| */ |
| protected void fillMultiRectAreaPaint(MultiRectArea mra) { |
| Rectangle rec = mra.getBounds(); |
| int x = rec.x; |
| int y = rec.y; |
| int w = rec.width; |
| int h = rec.height; |
| if(w <= 0 || h <= 0) { |
| return; |
| } |
| PaintContext pc = paint.createContext(null, rec, rec, transform, hints); |
| Raster r = pc.getRaster(x, y, w, h); |
| WritableRaster wr; |
| if(r instanceof WritableRaster){ |
| wr = (WritableRaster) r; |
| }else{ |
| wr = r.createCompatibleWritableRaster(); |
| wr.setRect(r); |
| } |
| Surface srcSurf = new ImageSurface(pc.getColorModel(), wr); |
| blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, |
| composite, null, mra); |
| srcSurf.dispose(); |
| } |
| |
| /** |
| * Copies graphics class fields. |
| * Used in create method |
| * |
| * @param copy Graphics class to copy |
| */ |
| protected void copyInternalFields(CommonGraphics2D copy) { |
| if (clip == null) { |
| copy.setTransformedClip(null); |
| } else { |
| copy.setTransformedClip(new MultiRectArea(clip)); |
| } |
| copy.setBackground(bgColor); |
| copy.setColor(fgColor); |
| copy.setPaint(paint); |
| copy.setComposite(composite); |
| copy.setStroke(stroke); |
| copy.setFont(font); |
| copy.setTransform(new AffineTransform(transform)); |
| //copy.origTransform = new AffineTransform(origTransform); |
| copy.origPoint = new Point(origPoint); |
| } |
| } |