/** * Copyright 2008 - 2015 The Loon Game Engine Authors * * Licensed 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. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.5 */ package loon.javase; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.WritableRaster; import java.util.Deque; import java.util.LinkedList; import loon.Graphics; import loon.canvas.Canvas; import loon.canvas.Gradient; import loon.canvas.Image; import loon.canvas.LColor; import loon.canvas.Path; import loon.canvas.Pattern; import loon.font.LFont; import loon.font.TextLayout; import loon.utils.MathUtils; class JavaSECanvas extends Canvas { final Graphics2D g2d; private Deque<JavaSECanvasState> stateStack = new LinkedList<JavaSECanvasState>(); private Ellipse2D.Float ellipse = new Ellipse2D.Float(); private Line2D.Float line = new Line2D.Float(); private Rectangle2D.Float rect = new Rectangle2D.Float(); private RoundRectangle2D.Float roundRect = new RoundRectangle2D.Float(); public JavaSECanvas(Graphics gfx, JavaSEImage image) { super(gfx, image); g2d = image.bufferedImage().createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); float scale = image.scale().factor; g2d.scale(scale, scale); stateStack.push(new JavaSECanvasState()); g2d.setBackground(new Color(0, true)); } public float alpha() { return currentState().alpha; } @Override public int getStrokeColor() { return currentState().strokeColor; } @Override public int getFillColor() { return currentState().fillColor; } public Canvas setColor(LColor color) { int argb = color.getARGB(); this.setStrokeColor(argb); this.setFillColor(argb); this.setAlpha(color.a); return this; } @Override public Canvas setColor(int r, int g, int b, int a) { int argb = LColor.getARGB(r, g, b, a); this.setStrokeColor(argb); this.setFillColor(argb); this.setAlpha(a); return null; } @Override public Canvas setColor(int r, int g, int b) { int rgb = LColor.getRGB(r, g, b); this.setStrokeColor(rgb); this.setFillColor(rgb); return null; } @Override public Image snapshot() { BufferedImage bmp = ((JavaSEImage) image).bufferedImage(); ColorModel cm = bmp.getColorModel(); boolean isAlphaPremultiplied = bmp.isAlphaPremultiplied(); WritableRaster raster = bmp.copyData(null); BufferedImage snap = new BufferedImage(cm, raster, isAlphaPremultiplied, null); return new JavaSEImage(gfx, image.scale(), snap, "<canvas>"); } @Override public Canvas clear() { currentState().prepareClear(g2d); g2d.clearRect(0, 0, MathUtils.iceil(width), MathUtils.iceil(height)); isDirty = true; return this; } @Override public Canvas clearRect(float x, float y, float width, float height) { currentState().prepareClear(g2d); g2d.clearRect(MathUtils.ifloor(x), MathUtils.ifloor(y), MathUtils.iceil(width), MathUtils.iceil(height)); isDirty = true; return this; } @Override public Canvas clip(Path path) { currentState().clipper = (JavaSEPath) path; return this; } @Override public Canvas clipRect(float x, float y, float width, final float height) { final int cx = MathUtils.ifloor(x), cy = MathUtils.ifloor(y); final int cwidth = MathUtils.iceil(width), cheight = MathUtils .iceil(height); currentState().clipper = new JavaSECanvasState.Clipper() { public void setClip(Graphics2D g2d) { g2d.setClip(cx, cy, cwidth, cheight); } }; return this; } @Override public Path createPath() { return new JavaSEPath(); } @Override public Gradient createGradient(Gradient.Config cfg) { if (cfg instanceof Gradient.Linear) { return JavaSEGradient.create((Gradient.Linear) cfg); } else if (cfg instanceof Gradient.Radial) { return JavaSEGradient.create((Gradient.Radial) cfg); } else { throw new IllegalArgumentException("Unknown config: " + cfg); } } @Override public Canvas drawLine(float x0, float y0, float x1, float y1) { currentState().prepareStroke(g2d); line.setLine(x0, y0, x1, y1); g2d.draw(line); isDirty = true; return this; } @Override public Canvas drawPoint(float x, float y) { currentState().prepareStroke(g2d); g2d.drawLine((int) x, (int) y, (int) x, (int) y); isDirty = true; return this; } @Override public Canvas drawText(String text, float x, float y) { if (_font == null) { _font = LFont.getDefaultFont(); } return fillText(_font.getLayoutText(text), x, y); } @Override public Canvas fillCircle(float x, float y, float radius) { currentState().prepareFill(g2d); ellipse.setFrame(x - radius, y - radius, 2 * radius, 2 * radius); g2d.fill(ellipse); isDirty = true; return this; } @Override public Canvas fillPath(Path path) { currentState().prepareFill(g2d); g2d.fill(((JavaSEPath) path).path); isDirty = true; return this; } @Override public Canvas fillRect(float x, float y, float width, float height) { currentState().prepareFill(g2d); rect.setRect(x, y, width, height); g2d.fill(rect); isDirty = true; return this; } @Override public Canvas fillRoundRect(float x, float y, float width, float height, float radius) { currentState().prepareFill(g2d); roundRect.setRoundRect(x, y, width, height, radius * 2, radius * 2); g2d.fill(roundRect); isDirty = true; return this; } @Override public Canvas fillText(TextLayout layout, float x, float y) { currentState().prepareFill(g2d); ((JavaSETextLayout) layout).fill(g2d, x, y); isDirty = true; return this; } @Override public Canvas restore() { stateStack.pop(); g2d.setTransform(currentState().transform); return this; } @Override public Canvas rotate(float angle) { g2d.rotate(angle); return this; } @Override public Canvas save() { currentState().transform = g2d.getTransform(); stateStack.push(new JavaSECanvasState(currentState())); return this; } @Override public Canvas scale(float x, float y) { g2d.scale(x, y); return this; } public Canvas setAlpha(float alpha) { if (alpha > 1f) { alpha = 1f; } currentState().alpha = alpha; return this; } @Override public Canvas setCompositeOperation(Composite composite) { currentState().composite = composite; return this; } @Override public Canvas setFillColor(int color) { currentState().fillColor = color; currentState().fillGradient = null; currentState().fillPattern = null; return this; } @Override public Canvas setFillGradient(Gradient gradient) { currentState().fillGradient = (JavaSEGradient) gradient; currentState().fillPattern = null; currentState().fillColor = 0; return this; } @Override public Canvas setFillPattern(Pattern pattern) { currentState().fillPattern = (JavaSEPattern) pattern; currentState().fillGradient = null; currentState().fillColor = 0; return this; } @Override public Canvas setLineCap(LineCap cap) { currentState().lineCap = cap; return this; } @Override public Canvas setLineJoin(LineJoin join) { currentState().lineJoin = join; return this; } @Override public Canvas setMiterLimit(float miter) { currentState().miterLimit = miter; return this; } @Override public Canvas setStrokeColor(int color) { currentState().strokeColor = color; return this; } @Override public Canvas setStrokeWidth(float w) { currentState().strokeWidth = w; return this; } @Override public Canvas strokeCircle(float x, float y, float radius) { currentState().prepareStroke(g2d); ellipse.setFrame(x - radius, y - radius, 2 * radius, 2 * radius); g2d.draw(ellipse); isDirty = true; return this; } @Override public Canvas strokePath(Path path) { currentState().prepareStroke(g2d); g2d.setColor(new Color(currentState().strokeColor, false)); g2d.draw(((JavaSEPath) path).path); isDirty = true; return this; } @Override public Canvas strokeRect(float x, float y, float width, float height) { currentState().prepareStroke(g2d); rect.setRect(x, y, width, height); g2d.draw(rect); isDirty = true; return this; } @Override public Canvas strokeRoundRect(float x, float y, float width, float height, float radius) { currentState().prepareStroke(g2d); roundRect.setRoundRect(x, y, width, height, radius * 2, radius * 2); g2d.draw(roundRect); isDirty = true; return this; } @Override public Canvas strokeText(TextLayout layout, float x, float y) { currentState().prepareStroke(g2d); ((JavaSETextLayout) layout).stroke(g2d, x, y); isDirty = true; return this; } @Override public Canvas transform(float m11, float m12, float m21, float m22, float dx, float dy) { g2d.transform(new AffineTransform(m11, m12, m21, m22, dx, dy)); return this; } @Override public Canvas translate(float x, float y) { g2d.translate(x, y); return this; } @Override protected Graphics2D gc() { currentState().prepareFill(g2d); return g2d; } private JavaSECanvasState currentState() { return stateStack.getFirst(); } }