package org.geogebra.web.html5.factories; import org.geogebra.common.awt.GAffineTransform; import org.geogebra.common.awt.GAlphaComposite; import org.geogebra.common.awt.GArc2D; import org.geogebra.common.awt.GArea; import org.geogebra.common.awt.GBasicStroke; import org.geogebra.common.awt.GBufferedImage; import org.geogebra.common.awt.GColor; import org.geogebra.common.awt.GDimension; import org.geogebra.common.awt.GEllipse2DDouble; import org.geogebra.common.awt.GFont; import org.geogebra.common.awt.GFontRenderContext; import org.geogebra.common.awt.GGeneralPath; import org.geogebra.common.awt.GGradientPaint; import org.geogebra.common.awt.GGraphics2D; import org.geogebra.common.awt.GLine2D; import org.geogebra.common.awt.GPaint; import org.geogebra.common.awt.GPoint2D; import org.geogebra.common.awt.GQuadCurve2D; import org.geogebra.common.awt.GRectangle; import org.geogebra.common.awt.GRectangle2D; import org.geogebra.common.awt.GShape; import org.geogebra.common.awt.MyImage; import org.geogebra.common.awt.font.GTextLayout; import org.geogebra.common.euclidian.event.FocusListener; import org.geogebra.common.factories.AwtFactory; import org.geogebra.common.main.App; import org.geogebra.ggbjdk.java.awt.DefaultBasicStroke; import org.geogebra.ggbjdk.java.awt.geom.AffineTransform; import org.geogebra.ggbjdk.java.awt.geom.Arc2D; import org.geogebra.ggbjdk.java.awt.geom.Area; import org.geogebra.ggbjdk.java.awt.geom.Ellipse2D; import org.geogebra.ggbjdk.java.awt.geom.GeneralPath; import org.geogebra.ggbjdk.java.awt.geom.Line2D; import org.geogebra.ggbjdk.java.awt.geom.Path2D; import org.geogebra.ggbjdk.java.awt.geom.Point2D; import org.geogebra.ggbjdk.java.awt.geom.QuadCurve2D; import org.geogebra.ggbjdk.java.awt.geom.Rectangle; import org.geogebra.ggbjdk.java.awt.geom.Rectangle2D; import org.geogebra.web.html5.awt.GAlphaCompositeW; import org.geogebra.web.html5.awt.GBasicStrokeW; import org.geogebra.web.html5.awt.GDimensionW; import org.geogebra.web.html5.awt.GFontRenderContextW; import org.geogebra.web.html5.awt.GFontW; import org.geogebra.web.html5.awt.GGradientPaintW; import org.geogebra.web.html5.awt.GTexturePaintW; import org.geogebra.web.html5.awt.font.GTextLayoutW; import org.geogebra.web.html5.euclidian.EuclidianViewW; import org.geogebra.web.html5.event.FocusListenerW; import org.geogebra.web.html5.gawt.GBufferedImageW; import org.geogebra.web.html5.main.MyImageW; import org.geogebra.web.html5.util.ImageLoadCallback; import org.geogebra.web.html5.util.ImageWrapper; import com.google.gwt.core.client.Scheduler; /** * Creates AWT wrappers for web * */ public class AwtFactoryW extends AwtFactory { @Override public GAffineTransform newAffineTransform() { return new AffineTransform(); } @Override public GRectangle2D newRectangle2D() { return new Rectangle2D.Double(); } @Override public GRectangle newRectangle(int x, int y, int w, int h) { return new Rectangle(x, y, w, h); } @Override public GBufferedImage newBufferedImage(int pixelWidth, int pixelHeight, double pixelRatio) { return new GBufferedImageW(pixelWidth, pixelHeight, pixelRatio); } @Override public GBufferedImage createBufferedImage(int width, int height, boolean transparency) { return null; // TODO } @Override public GDimension newDimension(int width, int height) { return new GDimensionW(width, height); } @Override public GPoint2D newPoint2D() { return new Point2D.Double(); } @Override public GPoint2D newPoint2D(double x, double y) { return new Point2D.Double(x, y); } @Override public GRectangle newRectangle(int x, int y) { return new Rectangle(x, y); } @Override public GGeneralPath newGeneralPath() { // default winding rule changed for ggb50 (for Polygons) #3983 return new GeneralPath(Path2D.WIND_EVEN_ODD); } @Override public GBasicStroke newMyBasicStroke(double f) { return new GBasicStrokeW(f, DefaultBasicStroke.CAP_ROUND, DefaultBasicStroke.JOIN_ROUND); } @Override public GBasicStroke newBasicStroke(double width, int endCap, int lineJoin, double miterLimit, double[] dash) { return new GBasicStrokeW(width, endCap, lineJoin, miterLimit, dash); } @Override public GLine2D newLine2D() { return new Line2D.Double(); } @Override public GRectangle newRectangle(GRectangle bb) { return new Rectangle(bb); } @Override public GEllipse2DDouble newEllipse2DDouble() { return new Ellipse2D.Double(); } @Override public GEllipse2DDouble newEllipse2DDouble(double i, double j, double k, double l) { return new Ellipse2D.Double(i, j, k, l); } @Override public GBasicStroke newBasicStroke(double f) { return new GBasicStrokeW(f); } @Override // CAP_BUTT, JOIN_MITER behaves differently on JRE & GWT // see #1699 public GBasicStroke newBasicStrokeJoinMitre(double f) { return new GBasicStrokeW(f, GBasicStroke.CAP_SQUARE, GBasicStroke.JOIN_MITER); } @Override public GRectangle newRectangle() { return new Rectangle(); } @Override public GArc2D newArc2D() { return new Arc2D.Double(); } @Override public GQuadCurve2D newQuadCurve2D() { return new QuadCurve2D.Double(); } /* * @Override public Area newArea(GeneralPathClipped hypRight) { * AbstractApplication.debug("implementation needed really"); // TODO * Auto-generated return null; } */ @Override public GArea newArea() { return new Area(); } @Override public GArea newArea(GShape shape) { return new Area(shape); } @Override public GGeneralPath newGeneralPath(int rule) { return new GeneralPath(rule); } @Override public GBasicStroke newBasicStroke(double f, int cap, int join) { return new GBasicStrokeW(f, cap, join); } @Override public GTextLayout newTextLayout(String string, GFont fontLine, GFontRenderContext frc) { return new GTextLayoutW(string, fontLine, (GFontRenderContextW) frc); } @Override public GAlphaComposite newAlphaComposite(double alpha) { return new GAlphaCompositeW(alpha); } @Override public GGradientPaint newGradientPaint(double x, double y, GColor bg2, double x2, double i, GColor bg) { return new GGradientPaintW(x, y, bg2, x2, i, bg); } @Override public FocusListener newFocusListener(Object listener) { return new FocusListenerW(listener); } @Override public GFont newFont(String name, int style, int size) { return new GFontW(name, style, size); } @Override public MyImage newMyImage(int pixelWidth, int pixelHeight, int typeIntArgb) { return new MyImageW(new GBufferedImageW(pixelWidth, pixelHeight, 1) .getImageElement(), false); } @Override public GPaint newTexturePaint(GBufferedImage subimage, GRectangle rect) { return new GTexturePaintW((GBufferedImageW) subimage); } @Override public GPaint newTexturePaint(MyImage subimage, GRectangle rect) { return new GTexturePaintW( new GBufferedImageW(((MyImageW) subimage).getImage())); } // to make code more efficient in the following method boolean repaintDeferred = false; // to avoid infinite loop in the following method int repaintsFromHereInProgress = 0; @Override public void fillAfterImageLoaded(final GShape shape, final GGraphics2D g3, GBufferedImage gi, final App app) { { if (((GBufferedImageW) gi).isLoaded()) { // when the image is already loaded, no new repaint is necessary // in theory, the image will be loaded after some repaints so // this will not be an infinite loop ... g3.fill(shape); } else if (repaintsFromHereInProgress == 0) { // the if condition makes sure there will be no infinite loop // note: AFAIK (?), DOM's addEventListener method can add more // listeners ImageWrapper.nativeon(((GBufferedImageW) gi).getImageElement(), "load", new ImageLoadCallback() { @Override public void onLoad() { if (!repaintDeferred) { repaintDeferred = true; // otherwise, at the first time, issue a // complete repaint // but schedule it deferred to avoid // conflicts // in repaints Scheduler.get().scheduleDeferred( new Scheduler.ScheduledCommand() { @Override public void execute() { repaintDeferred = false; repaintsFromHereInProgress++; ((EuclidianViewW) app .getEuclidianView1()) .doRepaint(); if (app.hasEuclidianView2( 1)) { ((EuclidianViewW) app .getEuclidianView2( 1)).doRepaint(); } repaintsFromHereInProgress--; } }); } } }); } } } }