0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: /**
0018: * @author Alexey A. Petrenko
0019: * @version $Revision$
0020: */package org.apache.harmony.awt.gl;
0021:
0022: import java.awt.AlphaComposite;
0023: import java.awt.BasicStroke;
0024: import java.awt.Color;
0025: import java.awt.Composite;
0026: import java.awt.Font;
0027: import java.awt.FontMetrics;
0028: import java.awt.Graphics2D;
0029: import java.awt.GraphicsConfiguration;
0030: import java.awt.Image;
0031: import java.awt.Paint;
0032: import java.awt.PaintContext;
0033: import java.awt.Point;
0034: import java.awt.Polygon;
0035: import java.awt.Rectangle;
0036: import java.awt.RenderingHints;
0037: import java.awt.Shape;
0038: import java.awt.Stroke;
0039: import java.awt.Toolkit;
0040: import java.awt.font.FontRenderContext;
0041: import java.awt.font.GlyphVector;
0042: import java.awt.geom.AffineTransform;
0043: import java.awt.geom.Arc2D;
0044: import java.awt.geom.Ellipse2D;
0045: import java.awt.geom.Line2D;
0046: import java.awt.geom.PathIterator;
0047: import java.awt.geom.RoundRectangle2D;
0048: import java.awt.image.AffineTransformOp;
0049: import java.awt.image.BufferedImage;
0050: import java.awt.image.BufferedImageOp;
0051: import java.awt.image.ImageObserver;
0052: import java.awt.image.Raster;
0053: import java.awt.image.RenderedImage;
0054: import java.awt.image.WritableRaster;
0055: import java.awt.image.renderable.RenderableImage;
0056: import java.text.AttributedCharacterIterator;
0057: import java.util.Collections;
0058: import java.util.HashMap;
0059: import java.util.Map;
0060:
0061: import org.apache.harmony.awt.gl.font.FontManager;
0062: import org.apache.harmony.awt.gl.font.fontlib.FLTextRenderer;
0063: import org.apache.harmony.awt.gl.image.OffscreenImage;
0064: import org.apache.harmony.awt.gl.render.Blitter;
0065: import org.apache.harmony.awt.gl.render.JavaArcRasterizer;
0066: import org.apache.harmony.awt.gl.render.JavaLineRasterizer;
0067: import org.apache.harmony.awt.gl.render.JavaShapeRasterizer;
0068: import org.apache.harmony.awt.gl.render.JavaTextRenderer;
0069: import org.apache.harmony.awt.gl.render.NullBlitter;
0070:
0071: /*
0072: * List of abstract methods to implement in subclusses
0073: * Graphics.copyArea(int x, int y, int width, int height, int dx, int dy)
0074: * Graphics.create()
0075: * Graphics2D.getDeviceConfiguration()
0076: * CommonGraphics2D.fillMultiRectAreaColor(MultiRectArea mra);
0077: * CommonGraphics2D.fillMultiRectAreaPaint(MultiRectArea mra);
0078: */
0079:
0080: /**
0081: * CommonGraphics2D class is a super class for all system-dependent
0082: * implementations. It implements major part of Graphics and Graphics2D
0083: * abstract methods.
0084: * <h2>CommonGraphics2D Class Internals</h2>
0085: * <h3>Line and Shape Rasterizers</h3>
0086: * <p>
0087: * The CommonGraphics2D class splits all shapes into a set of rectangles
0088: * to unify the drawing process for different operating systems and architectures.
0089: * For this purpose Java 2D* uses the JavaShapeRasterizer and the JavaLineRasterizer
0090: * classes from the org.apache.harmony.awt.gl.render package. The JavaShapeRasterizer
0091: * class splits an object implementing a Shape interface into a set of rectangles and
0092: * produces a MultiRectArea object. The JavaLineRasterizer class makes line drawing
0093: * more accurate and processes lines with strokes, which are instances of the BasicStroke
0094: * class.
0095: * </p>
0096: * <p>
0097: * To port the shape drawing to another platform you just need to override
0098: * rectangle-drawing methods. However, if your operating system has functions to draw
0099: * particular shapes, you can optimize your subclass of the CommonGraphics2D class by
0100: * using this functionality in overridden methods.
0101: * </p>
0102:
0103: * <h3>Blitters</h3>
0104: * <p>
0105: * Blitter classes draw images on the display or buffered images. All blitters inherit
0106: * the org.apache.harmony.awt.gl.render.Blitter interface.
0107: * </p>
0108: * <p>Blitters are divided into:
0109: * <ul>
0110: * <li>Native blitters for simple types of images, which the underlying native library
0111: * can draw.</li>
0112: * <li>Java* blitters for those types of images, which the underlying native library
0113: * cannot handle.</li>
0114: * </ul></p>
0115: * <p>
0116: * DRL Java 2D* also uses blitters to fill the shapes and the user-defined subclasses
0117: * of the java.awt.Paint class with paints, which the system does not support.
0118: * </p>
0119: *
0120: *<h3>Text Renderers</h3>
0121: *<p>
0122: *Text renderers draw strings and glyph vectors. All text renderers are subclasses
0123: *of the org.apache.harmony.awt.gl.TextRenderer class.
0124: *</p>
0125: *
0126: */
0127: public abstract class CommonGraphics2D extends Graphics2D {
0128:
0129: private static final Map<RenderingHints.Key, Object> DEFAULT_RENDERING_HINTS;
0130:
0131: static {
0132: final Map<RenderingHints.Key, Object> m = new HashMap<RenderingHints.Key, Object>();
0133:
0134: m.put(RenderingHints.KEY_TEXT_ANTIALIASING,
0135: RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
0136: m.put(RenderingHints.KEY_ANTIALIASING,
0137: RenderingHints.VALUE_ANTIALIAS_OFF);
0138: m.put(RenderingHints.KEY_STROKE_CONTROL,
0139: RenderingHints.VALUE_STROKE_DEFAULT);
0140:
0141: DEFAULT_RENDERING_HINTS = Collections.unmodifiableMap(m);
0142: }
0143:
0144: protected Surface dstSurf = null;
0145: protected Blitter blitter = NullBlitter.getInstance();
0146: protected RenderingHints hints = new RenderingHints(
0147: DEFAULT_RENDERING_HINTS);
0148:
0149: // Clipping things
0150: protected MultiRectArea clip = null;
0151:
0152: protected Paint paint = Color.WHITE;
0153: protected Color fgColor = Color.WHITE;
0154: protected Color bgColor = Color.BLACK;
0155:
0156: protected Composite composite = AlphaComposite.SrcOver;
0157:
0158: protected Stroke stroke = new BasicStroke();
0159:
0160: //TODO: Think more about FontRenderContext
0161: protected FontRenderContext frc = null;
0162:
0163: protected JavaShapeRasterizer jsr = new JavaShapeRasterizer();
0164:
0165: protected Font font = new Font("Dialog", Font.PLAIN, 12);; //$NON-NLS-1$
0166:
0167: protected TextRenderer jtr = FontManager.IS_FONTLIB ? FLTextRenderer
0168: .getInstance()
0169: : JavaTextRenderer.inst;
0170:
0171: // Current graphics transform
0172: protected AffineTransform transform = new AffineTransform();
0173: protected double[] matrix = new double[6];
0174:
0175: // Original user->device translation as transform and point
0176: //public AffineTransform origTransform = new AffineTransform();
0177: public Point origPoint = new Point(0, 0);
0178:
0179: // Print debug output or not
0180: protected static final boolean debugOutput = "1".equals(System.getProperty("g2d.debug")); //$NON-NLS-1$ //$NON-NLS-2$
0181:
0182: // Constructors
0183: protected CommonGraphics2D() {
0184: }
0185:
0186: protected CommonGraphics2D(int tx, int ty) {
0187: this (tx, ty, null);
0188: }
0189:
0190: protected CommonGraphics2D(int tx, int ty, MultiRectArea clip) {
0191: setTransform(AffineTransform.getTranslateInstance(tx, ty));
0192: //origTransform = AffineTransform.getTranslateInstance(tx, ty);
0193: origPoint = new Point(tx, ty);
0194: setClip(clip);
0195: }
0196:
0197: // Public methods
0198: @Override
0199: public void addRenderingHints(Map<?, ?> hints) {
0200: this .hints.putAll(hints);
0201: }
0202:
0203: @Override
0204: public void clearRect(int x, int y, int width, int height) {
0205: Color c = getColor();
0206: Paint p = getPaint();
0207: setColor(getBackground());
0208: fillRect(x, y, width, height);
0209: setColor(c);
0210: setPaint(p);
0211: if (debugOutput) {
0212: System.err
0213: .println("CommonGraphics2D.clearRect(" + x + ", " + y + ", " + width + ", " + height + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0214: }
0215: }
0216:
0217: @Override
0218: public void clipRect(int x, int y, int width, int height) {
0219: clip(new Rectangle(x, y, width, height));
0220: }
0221:
0222: @Override
0223: public void clip(Shape s) {
0224: if (s == null) {
0225: clip = null;
0226: return;
0227: }
0228:
0229: MultiRectArea mra = null;
0230: if (s instanceof MultiRectArea) {
0231: mra = new MultiRectArea((MultiRectArea) s);
0232: mra.translate((int) transform.getTranslateX(),
0233: (int) transform.getTranslateY());
0234: } else {
0235: int type = transform.getType();
0236: if (s instanceof Rectangle
0237: && (type & (AffineTransform.TYPE_IDENTITY | AffineTransform.TYPE_TRANSLATION)) != 0) {
0238: mra = new MultiRectArea((Rectangle) s);
0239: if (type == AffineTransform.TYPE_TRANSLATION) {
0240: mra.translate((int) transform.getTranslateX(),
0241: (int) transform.getTranslateY());
0242: }
0243: } else {
0244: s = transform.createTransformedShape(s);
0245: mra = jsr.rasterize(s, 0.5);
0246: }
0247: }
0248:
0249: if (clip == null) {
0250: setTransformedClip(mra);
0251: } else {
0252: clip.intersect(mra);
0253: setTransformedClip(clip);
0254: }
0255: }
0256:
0257: @Override
0258: public void dispose() {
0259: // Do nothing for Java only classes
0260: }
0261:
0262: /***************************************************************************
0263: *
0264: * Draw methods
0265: *
0266: ***************************************************************************/
0267:
0268: @Override
0269: public void draw(Shape s) {
0270: if (stroke instanceof BasicStroke
0271: && ((BasicStroke) stroke).getLineWidth() <= 1) {
0272: //TODO: Think about drawing the shape in one fillMultiRectArea call
0273: BasicStroke bstroke = (BasicStroke) stroke;
0274: JavaLineRasterizer.LineDasher ld = (bstroke.getDashArray() == null) ? null
0275: : new JavaLineRasterizer.LineDasher(bstroke
0276: .getDashArray(), bstroke.getDashPhase());
0277: PathIterator pi = s.getPathIterator(transform, 0.5);
0278: float[] points = new float[6];
0279: int x1 = Integer.MIN_VALUE;
0280: int y1 = Integer.MIN_VALUE;
0281: int cx1 = Integer.MIN_VALUE;
0282: int cy1 = Integer.MIN_VALUE;
0283: while (!pi.isDone()) {
0284: switch (pi.currentSegment(points)) {
0285: case PathIterator.SEG_MOVETO:
0286: x1 = (int) Math.floor(points[0]);
0287: y1 = (int) Math.floor(points[1]);
0288: cx1 = x1;
0289: cy1 = y1;
0290: break;
0291: case PathIterator.SEG_LINETO:
0292: int x2 = (int) Math.floor(points[0]);
0293: int y2 = (int) Math.floor(points[1]);
0294: fillMultiRectArea(JavaLineRasterizer.rasterize(x1,
0295: y1, x2, y2, null, ld, false));
0296: x1 = x2;
0297: y1 = y2;
0298: break;
0299: case PathIterator.SEG_CLOSE:
0300: x2 = cx1;
0301: y2 = cy1;
0302: fillMultiRectArea(JavaLineRasterizer.rasterize(x1,
0303: y1, x2, y2, null, ld, false));
0304: x1 = x2;
0305: y1 = y2;
0306: break;
0307: }
0308: pi.next();
0309: }
0310: } else {
0311: s = stroke.createStrokedShape(s);
0312: s = transform.createTransformedShape(s);
0313: fillMultiRectArea(jsr.rasterize(s, 0.5));
0314: }
0315: }
0316:
0317: @Override
0318: public void drawArc(int x, int y, int width, int height, int sa,
0319: int ea) {
0320: if (stroke instanceof BasicStroke
0321: && ((BasicStroke) stroke).getLineWidth() <= 1
0322: && ((BasicStroke) stroke).getDashArray() == null
0323: && (transform.isIdentity() || transform.getType() == AffineTransform.TYPE_TRANSLATION)) {
0324: Point p = new Point(x, y);
0325: transform.transform(p, p);
0326: MultiRectArea mra = JavaArcRasterizer.rasterize(x, y,
0327: width, height, sa, ea, clip);
0328: fillMultiRectArea(mra);
0329: return;
0330: }
0331: draw(new Arc2D.Float(x, y, width, height, sa, ea, Arc2D.OPEN));
0332: }
0333:
0334: @Override
0335: public boolean drawImage(Image image, int x, int y, Color bgcolor,
0336: ImageObserver imageObserver) {
0337:
0338: if (image == null) {
0339: return true;
0340: }
0341:
0342: boolean done = false;
0343: boolean somebits = false;
0344: Surface srcSurf = null;
0345: if (image instanceof OffscreenImage) {
0346: OffscreenImage oi = (OffscreenImage) image;
0347: if ((oi.getState() & ImageObserver.ERROR) != 0) {
0348: return false;
0349: }
0350: done = oi.prepareImage(imageObserver);
0351: somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
0352: srcSurf = oi.getImageSurface();
0353: } else {
0354: done = true;
0355: srcSurf = Surface.getImageSurface(image);
0356: }
0357:
0358: if (done || somebits) {
0359: int w = srcSurf.getWidth();
0360: int h = srcSurf.getHeight();
0361: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
0362: (AffineTransform) transform.clone(), composite,
0363: bgcolor, clip);
0364: }
0365: return done;
0366: }
0367:
0368: @Override
0369: public boolean drawImage(Image image, int x, int y,
0370: ImageObserver imageObserver) {
0371: return drawImage(image, x, y, null, imageObserver);
0372: }
0373:
0374: @Override
0375: public boolean drawImage(Image image, int x, int y, int width,
0376: int height, Color bgcolor, ImageObserver imageObserver) {
0377:
0378: if (image == null) {
0379: return true;
0380: }
0381: if (width == 0 || height == 0) {
0382: return true;
0383: }
0384:
0385: boolean done = false;
0386: boolean somebits = false;
0387: Surface srcSurf = null;
0388:
0389: if (image instanceof OffscreenImage) {
0390: OffscreenImage oi = (OffscreenImage) image;
0391: if ((oi.getState() & ImageObserver.ERROR) != 0) {
0392: return false;
0393: }
0394: done = oi.prepareImage(imageObserver);
0395: somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
0396: srcSurf = oi.getImageSurface();
0397: } else {
0398: done = true;
0399: srcSurf = Surface.getImageSurface(image);
0400: }
0401:
0402: if (done || somebits) {
0403: int w = srcSurf.getWidth();
0404: int h = srcSurf.getHeight();
0405: if (w == width && h == height) {
0406: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
0407: (AffineTransform) transform.clone(), composite,
0408: bgcolor, clip);
0409: } else {
0410: AffineTransform xform = new AffineTransform();
0411: xform.setToScale((float) width / w, (float) height / h);
0412: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
0413: (AffineTransform) transform.clone(), xform,
0414: composite, bgcolor, clip);
0415: }
0416: }
0417: return done;
0418: }
0419:
0420: @Override
0421: public boolean drawImage(Image image, int x, int y, int width,
0422: int height, ImageObserver imageObserver) {
0423: return drawImage(image, x, y, width, height, null,
0424: imageObserver);
0425: }
0426:
0427: @Override
0428: public boolean drawImage(Image image, int dx1, int dy1, int dx2,
0429: int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor,
0430: ImageObserver imageObserver) {
0431:
0432: if (image == null) {
0433: return true;
0434: }
0435: if (dx1 == dx2 || dy1 == dy2 || sx1 == sx2 || sy1 == sy2) {
0436: return true;
0437: }
0438:
0439: boolean done = false;
0440: boolean somebits = false;
0441: Surface srcSurf = null;
0442: if (image instanceof OffscreenImage) {
0443: OffscreenImage oi = (OffscreenImage) image;
0444: if ((oi.getState() & ImageObserver.ERROR) != 0) {
0445: return false;
0446: }
0447: done = oi.prepareImage(imageObserver);
0448: somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
0449: srcSurf = oi.getImageSurface();
0450: } else {
0451: done = true;
0452: srcSurf = Surface.getImageSurface(image);
0453: }
0454:
0455: if (done || somebits) {
0456:
0457: int dstX = dx1;
0458: int dstY = dy1;
0459: int srcX = sx1;
0460: int srcY = sy1;
0461:
0462: int dstW = dx2 - dx1;
0463: int dstH = dy2 - dy1;
0464: int srcW = sx2 - sx1;
0465: int srcH = sy2 - sy1;
0466:
0467: if (srcW == dstW && srcH == dstH) {
0468: blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf,
0469: srcW, srcH,
0470: (AffineTransform) transform.clone(), composite,
0471: bgcolor, clip);
0472: } else {
0473: AffineTransform xform = new AffineTransform();
0474: xform.setToScale((float) dstW / srcW, (float) dstH
0475: / srcH);
0476: blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf,
0477: srcW, srcH,
0478: (AffineTransform) transform.clone(), xform,
0479: composite, bgcolor, clip);
0480: }
0481: }
0482: return done;
0483: }
0484:
0485: @Override
0486: public boolean drawImage(Image image, int dx1, int dy1, int dx2,
0487: int dy2, int sx1, int sy1, int sx2, int sy2,
0488: ImageObserver imageObserver) {
0489:
0490: return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
0491: null, imageObserver);
0492: }
0493:
0494: @Override
0495: public void drawImage(BufferedImage bufImage, BufferedImageOp op,
0496: int x, int y) {
0497:
0498: if (bufImage == null) {
0499: return;
0500: }
0501:
0502: if (op == null) {
0503: drawImage(bufImage, x, y, null);
0504: } else if (op instanceof AffineTransformOp) {
0505: AffineTransformOp atop = (AffineTransformOp) op;
0506: AffineTransform xform = atop.getTransform();
0507: Surface srcSurf = Surface.getImageSurface(bufImage);
0508: int w = srcSurf.getWidth();
0509: int h = srcSurf.getHeight();
0510: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
0511: (AffineTransform) transform.clone(), xform,
0512: composite, null, clip);
0513: } else {
0514: bufImage = op.filter(bufImage, null);
0515: Surface srcSurf = Surface.getImageSurface(bufImage);
0516: int w = srcSurf.getWidth();
0517: int h = srcSurf.getHeight();
0518: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
0519: (AffineTransform) transform.clone(), composite,
0520: null, clip);
0521: }
0522: }
0523:
0524: @Override
0525: public boolean drawImage(Image image, AffineTransform trans,
0526: ImageObserver imageObserver) {
0527:
0528: if (image == null) {
0529: return true;
0530: }
0531: if (trans == null || trans.isIdentity()) {
0532: return drawImage(image, 0, 0, imageObserver);
0533: }
0534:
0535: boolean done = false;
0536: boolean somebits = false;
0537: Surface srcSurf = null;
0538: if (image instanceof OffscreenImage) {
0539: OffscreenImage oi = (OffscreenImage) image;
0540: if ((oi.getState() & ImageObserver.ERROR) != 0) {
0541: return false;
0542: }
0543: done = oi.prepareImage(imageObserver);
0544: somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
0545: srcSurf = oi.getImageSurface();
0546: } else {
0547: done = true;
0548: srcSurf = Surface.getImageSurface(image);
0549: }
0550:
0551: if (done || somebits) {
0552: int w = srcSurf.getWidth();
0553: int h = srcSurf.getHeight();
0554: AffineTransform xform = (AffineTransform) transform.clone();
0555: xform.concatenate(trans);
0556: blitter.blit(0, 0, srcSurf, 0, 0, dstSurf, w, h, xform,
0557: composite, null, clip);
0558: }
0559: return done;
0560: }
0561:
0562: @Override
0563: public void drawLine(int x1, int y1, int x2, int y2) {
0564: if (debugOutput) {
0565: System.err
0566: .println("CommonGraphics2D.drawLine(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0567: }
0568:
0569: if (stroke instanceof BasicStroke
0570: && ((BasicStroke) stroke).getLineWidth() <= 1) {
0571: BasicStroke bstroke = (BasicStroke) stroke;
0572: Point p1 = new Point(x1, y1);
0573: Point p2 = new Point(x2, y2);
0574: transform.transform(p1, p1);
0575: transform.transform(p2, p2);
0576: JavaLineRasterizer.LineDasher ld = (bstroke.getDashArray() == null) ? null
0577: : new JavaLineRasterizer.LineDasher(bstroke
0578: .getDashArray(), bstroke.getDashPhase());
0579: MultiRectArea mra = JavaLineRasterizer.rasterize(p1.x,
0580: p1.y, p2.x, p2.y, null, ld, false);
0581: fillMultiRectArea(mra);
0582: return;
0583: }
0584: draw(new Line2D.Float(x1, y1, x2, y2));
0585: }
0586:
0587: @Override
0588: public void drawOval(int x, int y, int width, int height) {
0589: if (stroke instanceof BasicStroke
0590: && ((BasicStroke) stroke).getLineWidth() <= 1
0591: && ((BasicStroke) stroke).getDashArray() == null
0592: && (transform.isIdentity() || transform.getType() == AffineTransform.TYPE_TRANSLATION)) {
0593: Point p = new Point(x, y);
0594: transform.transform(p, p);
0595: MultiRectArea mra = JavaArcRasterizer.rasterize(p.x, p.y,
0596: width, height, 0, 360, clip);
0597: fillMultiRectArea(mra);
0598: return;
0599: }
0600: draw(new Ellipse2D.Float(x, y, width, height));
0601: }
0602:
0603: @Override
0604: public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) {
0605: draw(new Polygon(xpoints, ypoints, npoints));
0606: }
0607:
0608: @Override
0609: public void drawPolygon(Polygon polygon) {
0610: draw(polygon);
0611: }
0612:
0613: @Override
0614: public void drawPolyline(int[] xpoints, int[] ypoints, int npoints) {
0615: for (int i = 0; i < npoints - 1; i++) {
0616: drawLine(xpoints[i], ypoints[i], xpoints[i + 1],
0617: ypoints[i + 1]);
0618: }
0619: }
0620:
0621: @Override
0622: public void drawRenderableImage(RenderableImage img,
0623: AffineTransform xform) {
0624: if (img == null) {
0625: return;
0626: }
0627:
0628: double scaleX = xform.getScaleX();
0629: double scaleY = xform.getScaleY();
0630: if (scaleX == 1 && scaleY == 1) {
0631: drawRenderedImage(img.createDefaultRendering(), xform);
0632: } else {
0633: int width = (int) Math.round(img.getWidth() * scaleX);
0634: int height = (int) Math.round(img.getHeight() * scaleY);
0635: xform = (AffineTransform) xform.clone();
0636: xform.scale(1, 1);
0637: drawRenderedImage(img.createScaledRendering(width, height,
0638: null), xform);
0639: }
0640: }
0641:
0642: @Override
0643: public void drawRenderedImage(RenderedImage rimg,
0644: AffineTransform xform) {
0645: if (rimg == null) {
0646: return;
0647: }
0648:
0649: Image img = null;
0650:
0651: if (rimg instanceof Image) {
0652: img = (Image) rimg;
0653: } else {
0654: //TODO: Create new class to provide Image interface for RenderedImage or rewrite this method
0655: img = new BufferedImage(rimg.getColorModel(), rimg
0656: .copyData(null), false, null);
0657: }
0658:
0659: drawImage(img, xform, null);
0660: }
0661:
0662: @Override
0663: public void drawRoundRect(int x, int y, int width, int height,
0664: int arcWidth, int arcHeight) {
0665: if (debugOutput) {
0666: System.err
0667: .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$
0668: }
0669:
0670: draw(new RoundRectangle2D.Float(x, y, width, height, arcWidth,
0671: arcHeight));
0672: }
0673:
0674: /***************************************************************************
0675: *
0676: * String methods
0677: *
0678: ***************************************************************************/
0679:
0680: @Override
0681: public void drawString(AttributedCharacterIterator iterator,
0682: float x, float y) {
0683: GlyphVector gv = font.createGlyphVector(frc, iterator);
0684: drawGlyphVector(gv, x, y);
0685: }
0686:
0687: @Override
0688: public void drawString(AttributedCharacterIterator iterator, int x,
0689: int y) {
0690: drawString(iterator, (float) x, (float) y);
0691: }
0692:
0693: @Override
0694: public void drawString(String str, int x, int y) {
0695: drawString(str, (float) x, (float) y);
0696: }
0697:
0698: /***************************************************************************
0699: *
0700: * Fill methods
0701: *
0702: ***************************************************************************/
0703:
0704: @Override
0705: public void fill(Shape s) {
0706: s = transform.createTransformedShape(s);
0707: MultiRectArea mra = jsr.rasterize(s, 0.5);
0708: fillMultiRectArea(mra);
0709: }
0710:
0711: @Override
0712: public void fillArc(int x, int y, int width, int height, int sa,
0713: int ea) {
0714: fill(new Arc2D.Float(x, y, width, height, sa, ea, Arc2D.PIE));
0715: }
0716:
0717: @Override
0718: public void fillOval(int x, int y, int width, int height) {
0719: fill(new Ellipse2D.Float(x, y, width, height));
0720: }
0721:
0722: @Override
0723: public void fillPolygon(int[] xpoints, int[] ypoints, int npoints) {
0724: fill(new Polygon(xpoints, ypoints, npoints));
0725: }
0726:
0727: @Override
0728: public void fillPolygon(Polygon polygon) {
0729: fill(polygon);
0730: }
0731:
0732: @Override
0733: public void fillRect(int x, int y, int width, int height) {
0734: if (debugOutput) {
0735: System.err
0736: .println("CommonGraphics2D.fillRect(" + x + ", " + y + ", " + width + ", " + height + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
0737: }
0738:
0739: fill(new Rectangle(x, y, width, height));
0740: }
0741:
0742: @Override
0743: public void fillRoundRect(int x, int y, int width, int height,
0744: int arcWidth, int arcHeight) {
0745: if (debugOutput) {
0746: System.err
0747: .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$
0748: }
0749:
0750: fill(new RoundRectangle2D.Float(x, y, width, height, arcWidth,
0751: arcHeight));
0752: }
0753:
0754: /***************************************************************************
0755: *
0756: * Get methods
0757: *
0758: ***************************************************************************/
0759:
0760: @Override
0761: public Color getBackground() {
0762: return bgColor;
0763: }
0764:
0765: @Override
0766: public Shape getClip() {
0767: if (clip == null) {
0768: return null;
0769: }
0770:
0771: MultiRectArea res = new MultiRectArea(clip);
0772: res.translate(-Math.round((float) transform.getTranslateX()),
0773: -Math.round((float) transform.getTranslateY()));
0774: return res;
0775: }
0776:
0777: @Override
0778: public Rectangle getClipBounds() {
0779: if (clip == null) {
0780: return null;
0781: }
0782:
0783: Rectangle res = (Rectangle) clip.getBounds().clone();
0784: res.translate(-Math.round((float) transform.getTranslateX()),
0785: -Math.round((float) transform.getTranslateY()));
0786: return res;
0787: }
0788:
0789: @Override
0790: public Color getColor() {
0791: return fgColor;
0792: }
0793:
0794: @Override
0795: public Composite getComposite() {
0796: return composite;
0797: }
0798:
0799: @Override
0800: public Font getFont() {
0801: return font;
0802: }
0803:
0804: @SuppressWarnings("deprecation")
0805: @Override
0806: public FontMetrics getFontMetrics(Font font) {
0807: return Toolkit.getDefaultToolkit().getFontMetrics(font);
0808: }
0809:
0810: @Override
0811: public FontRenderContext getFontRenderContext() {
0812: AffineTransform at;
0813: if (frc == null) {
0814: GraphicsConfiguration gc = getDeviceConfiguration();
0815: if (gc != null) {
0816: at = gc.getDefaultTransform();
0817: at.concatenate(gc.getNormalizingTransform());
0818: } else
0819: at = null;
0820:
0821: boolean isAa = (hints
0822: .get(RenderingHints.KEY_TEXT_ANTIALIASING) == RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
0823: boolean isFm = (hints
0824: .get(RenderingHints.KEY_FRACTIONALMETRICS) == RenderingHints.VALUE_FRACTIONALMETRICS_ON);
0825: frc = new FontRenderContext(at, isAa, isFm);
0826: }
0827: return frc;
0828: }
0829:
0830: @Override
0831: public Paint getPaint() {
0832: return paint;
0833: }
0834:
0835: @Override
0836: public Object getRenderingHint(RenderingHints.Key key) {
0837: return hints.get(key);
0838: }
0839:
0840: @Override
0841: public RenderingHints getRenderingHints() {
0842: return hints;
0843: }
0844:
0845: @Override
0846: public Stroke getStroke() {
0847: return stroke;
0848: }
0849:
0850: @Override
0851: public AffineTransform getTransform() {
0852: return (AffineTransform) transform.clone();
0853: }
0854:
0855: @Override
0856: public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
0857: //TODO: Implement method....
0858: return false;
0859: }
0860:
0861: /***************************************************************************
0862: *
0863: * Transformation methods
0864: *
0865: ***************************************************************************/
0866:
0867: @Override
0868: public void rotate(double theta) {
0869: transform.rotate(theta);
0870: transform.getMatrix(matrix);
0871: }
0872:
0873: @Override
0874: public void rotate(double theta, double x, double y) {
0875: transform.rotate(theta, x, y);
0876: transform.getMatrix(matrix);
0877: }
0878:
0879: @Override
0880: public void scale(double sx, double sy) {
0881: transform.scale(sx, sy);
0882: transform.getMatrix(matrix);
0883: }
0884:
0885: @Override
0886: public void shear(double shx, double shy) {
0887: transform.shear(shx, shy);
0888: transform.getMatrix(matrix);
0889: }
0890:
0891: @Override
0892: public void transform(AffineTransform at) {
0893: transform.concatenate(at);
0894: transform.getMatrix(matrix);
0895: }
0896:
0897: @Override
0898: public void translate(double tx, double ty) {
0899: if (debugOutput) {
0900: System.err
0901: .println("CommonGraphics2D.translate(" + tx + ", " + ty + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0902: }
0903:
0904: transform.translate(tx, ty);
0905: transform.getMatrix(matrix);
0906: }
0907:
0908: @Override
0909: public void translate(int tx, int ty) {
0910: if (debugOutput) {
0911: System.err
0912: .println("CommonGraphics2D.translate(" + tx + ", " + ty + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
0913: }
0914:
0915: transform.translate(tx, ty);
0916: transform.getMatrix(matrix);
0917: }
0918:
0919: /***************************************************************************
0920: *
0921: * Set methods
0922: *
0923: ***************************************************************************/
0924:
0925: @Override
0926: public void setBackground(Color color) {
0927: bgColor = color;
0928: }
0929:
0930: @Override
0931: public void setClip(int x, int y, int width, int height) {
0932: setClip(new Rectangle(x, y, width, height));
0933: }
0934:
0935: @Override
0936: public void setClip(Shape s) {
0937: if (s == null) {
0938: setTransformedClip(null);
0939: if (debugOutput) {
0940: System.err.println("CommonGraphics2D.setClip(null)"); //$NON-NLS-1$
0941: }
0942: return;
0943: }
0944:
0945: if (debugOutput) {
0946: System.err
0947: .println("CommonGraphics2D.setClip(" + s.getBounds() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
0948: }
0949:
0950: if (s instanceof MultiRectArea) {
0951: MultiRectArea nclip = new MultiRectArea((MultiRectArea) s);
0952: nclip.translate(Math.round((float) transform
0953: .getTranslateX()), Math.round((float) transform
0954: .getTranslateY()));
0955: setTransformedClip(nclip);
0956: } else {
0957: int type = transform.getType();
0958: if (s instanceof Rectangle
0959: && (type & (AffineTransform.TYPE_IDENTITY | AffineTransform.TYPE_TRANSLATION)) != 0) {
0960: MultiRectArea nclip = new MultiRectArea((Rectangle) s);
0961: if (type == AffineTransform.TYPE_TRANSLATION) {
0962: nclip.translate((int) transform.getTranslateX(),
0963: (int) transform.getTranslateY());
0964: }
0965: setTransformedClip(nclip);
0966: } else {
0967: s = transform.createTransformedShape(s);
0968: setTransformedClip(jsr.rasterize(s, 0.5));
0969: }
0970: }
0971: }
0972:
0973: @Override
0974: public void setColor(Color color) {
0975: if (color != null) {
0976: fgColor = color;
0977: paint = color;
0978: }
0979: }
0980:
0981: @Override
0982: public void setComposite(Composite composite) {
0983: this .composite = composite;
0984: }
0985:
0986: @Override
0987: public void setFont(Font font) {
0988: this .font = font;
0989: }
0990:
0991: @Override
0992: public void setPaint(Paint paint) {
0993: if (paint == null)
0994: return;
0995:
0996: this .paint = paint;
0997: if (paint instanceof Color) {
0998: fgColor = (Color) paint;
0999: }
1000: }
1001:
1002: @Override
1003: public void setPaintMode() {
1004: composite = AlphaComposite.SrcOver;
1005: }
1006:
1007: @Override
1008: public void setRenderingHint(RenderingHints.Key key, Object value) {
1009: hints.put(key, value);
1010: }
1011:
1012: @Override
1013: public void setRenderingHints(Map<?, ?> hints) {
1014: this .hints.clear();
1015: this .hints.putAll(DEFAULT_RENDERING_HINTS);
1016: this .hints.putAll(hints);
1017: }
1018:
1019: @Override
1020: public void setStroke(Stroke stroke) {
1021: this .stroke = stroke;
1022: }
1023:
1024: @Override
1025: public void setTransform(AffineTransform transform) {
1026: this .transform = transform;
1027:
1028: transform.getMatrix(matrix);
1029: }
1030:
1031: @Override
1032: public void setXORMode(Color color) {
1033: composite = new XORComposite(color);
1034: }
1035:
1036: // Protected methods
1037: protected void setTransformedClip(MultiRectArea clip) {
1038: this .clip = clip;
1039: }
1040:
1041: /**
1042: * This method fills the given MultiRectArea with current paint.
1043: * It calls fillMultiRectAreaColor and fillMultiRectAreaPaint
1044: * methods depending on the type of current paint.
1045: * @param mra MultiRectArea to fill
1046: */
1047: protected void fillMultiRectArea(MultiRectArea mra) {
1048: if (clip != null) {
1049: mra.intersect(clip);
1050: }
1051:
1052: // Return if all stuff is clipped
1053: if (mra.rect[0] < 5) {
1054: return;
1055: }
1056:
1057: if (debugOutput) {
1058: System.err
1059: .println("CommonGraphics2D.fillMultiRectArea(" + mra + ")"); //$NON-NLS-1$ //$NON-NLS-2$
1060: }
1061:
1062: if (paint instanceof Color) {
1063: fillMultiRectAreaColor(mra);
1064: } else {
1065: fillMultiRectAreaPaint(mra);
1066: }
1067: }
1068:
1069: /**
1070: * This method fills the given MultiRectArea with solid color.
1071: * @param mra MultiRectArea to fill
1072: */
1073: protected void fillMultiRectAreaColor(MultiRectArea mra) {
1074: fillMultiRectAreaPaint(mra);
1075: }
1076:
1077: /**
1078: * This method fills the given MultiRectArea with any paint.
1079: * @param mra MultiRectArea to fill
1080: */
1081: protected void fillMultiRectAreaPaint(MultiRectArea mra) {
1082: Rectangle rec = mra.getBounds();
1083: int x = rec.x;
1084: int y = rec.y;
1085: int w = rec.width;
1086: int h = rec.height;
1087: if (w <= 0 || h <= 0) {
1088: return;
1089: }
1090: PaintContext pc = paint.createContext(null, rec, rec,
1091: transform, hints);
1092: Raster r = pc.getRaster(x, y, w, h);
1093: WritableRaster wr;
1094: if (r instanceof WritableRaster) {
1095: wr = (WritableRaster) r;
1096: } else {
1097: wr = r.createCompatibleWritableRaster();
1098: wr.setRect(r);
1099: }
1100: Surface srcSurf = new ImageSurface(pc.getColorModel(), wr);
1101: blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, composite,
1102: null, mra);
1103: srcSurf.dispose();
1104: }
1105:
1106: /**
1107: * Copies graphics class fields.
1108: * Used in create method
1109: *
1110: * @param copy Graphics class to copy
1111: */
1112: protected void copyInternalFields(CommonGraphics2D copy) {
1113: if (clip == null) {
1114: copy.setTransformedClip(null);
1115: } else {
1116: copy.setTransformedClip(new MultiRectArea(clip));
1117: }
1118: copy.setBackground(bgColor);
1119: copy.setColor(fgColor);
1120: copy.setPaint(paint);
1121: copy.setComposite(composite);
1122: copy.setStroke(stroke);
1123: copy.setFont(font);
1124: copy.setTransform(new AffineTransform(transform));
1125: //copy.origTransform = new AffineTransform(origTransform);
1126: copy.origPoint = new Point(origPoint);
1127: }
1128: }
|