/**
* 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.android;
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.TextLayout;
import loon.utils.MathUtils;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
public class AndroidCanvas extends Canvas {
private static Matrix m = new Matrix();
private static Rect srcR = new Rect();
private static RectF dstR = new RectF();
private final android.graphics.Canvas canvas;
private final LinkedList<AndroidCanvasState> paintStack = new LinkedList<>();
public AndroidCanvas(Graphics gfx, AndroidImage image) {
super(gfx, image);
canvas = new android.graphics.Canvas(image.bitmap());
paintStack.addFirst(new AndroidCanvasState());
float factor = image.scale().factor;
scale(factor, factor);
}
void draw(Bitmap bitmap, float x, float y, float w, float h, float x1,
float y1, float w1, float h1) {
srcR.set((int) x1, (int) y1, (int) w1, (int) h1);
dstR.set(x, y, x + w, y + h);
canvas.drawBitmap(bitmap, srcR, dstR, currentState().prepareImage());
isDirty = true;
}
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 int getStrokeColor() {
return currentState().strokeColor;
}
@Override
public int getFillColor() {
return currentState().fillColor;
}
public float alpha() {
return currentState().alpha;
}
@Override
public Canvas clear() {
canvas.drawColor(0, PorterDuff.Mode.SRC);
isDirty = true;
return this;
}
@Override
public Canvas clearRect(float x, float y, float width, float height) {
canvas.save(android.graphics.Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(x, y, x + width, y + height);
canvas.drawColor(0, PorterDuff.Mode.SRC);
canvas.restore();
isDirty = true;
return this;
}
@Override
public Canvas clip(Path clipPath) {
canvas.clipPath(((AndroidPath) clipPath).path);
return this;
}
@Override
public Canvas clipRect(float x, float y, float width, float height) {
canvas.clipRect(x, y, x + width, y + height);
return this;
}
@Override
public Path createPath() {
return new AndroidPath();
}
@Override
public Gradient createGradient(Gradient.Config cfg) {
return new AndroidGradient(cfg);
}
@Override
public Canvas drawLine(float x0, float y0, float x1, float y1) {
canvas.drawLine(x0, y0, x1, y1, currentState().prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas drawPoint(float x, float y) {
canvas.drawPoint(x, y, currentState().prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas drawText(String text, float x, float y) {
return fillText(_font.getLayoutText(text), x, y);
}
@Override
public Canvas fillCircle(float x, float y, float radius) {
canvas.drawCircle(x, y, radius, currentState().prepareFill());
isDirty = true;
return this;
}
@Override
public Canvas fillPath(Path path) {
canvas.drawPath(((AndroidPath) path).path, currentState().prepareFill());
isDirty = true;
return this;
}
@Override
public Canvas fillRect(float x, float y, float width, float height) {
float left = x;
float top = y;
float right = left + width;
float bottom = top + height;
canvas.drawRect(left, top, right, bottom, currentState().prepareFill());
isDirty = true;
return this;
}
@Override
public Canvas fillRoundRect(float x, float y, float width, float height,
float radius) {
canvas.translate(x, y);
dstR.set(0, 0, width, height);
canvas.drawRoundRect(dstR, radius, radius, currentState().prepareFill());
canvas.translate(-x, -y);
isDirty = true;
return this;
}
@Override
public Canvas fillText(TextLayout layout, float x, float y) {
((AndroidTextLayout) layout).draw(canvas, x, y, currentState()
.prepareFill());
isDirty = true;
return this;
}
@Override
public Canvas restore() {
canvas.restore();
paintStack.removeFirst();
return this;
}
@Override
public Canvas rotate(float angle) {
canvas.rotate(MathUtils.degToRad(angle));
return this;
}
@Override
public Canvas save() {
canvas.save();
paintStack.addFirst(new AndroidCanvasState(currentState()));
return this;
}
@Override
public Canvas scale(float x, float y) {
canvas.scale(x, y);
return this;
}
@Override
public Canvas setAlpha(float alpha) {
currentState().setAlpha(alpha);
return this;
}
@Override
public Canvas setCompositeOperation(Composite composite) {
currentState().setCompositeOperation(composite);
return this;
}
@Override
public Canvas setFillColor(int color) {
currentState().setFillColor(color);
return this;
}
@Override
public Canvas setFillGradient(Gradient gradient) {
currentState().setFillGradient((AndroidGradient) gradient);
return this;
}
@Override
public Canvas setFillPattern(Pattern pattern) {
currentState().setFillPattern((AndroidPattern) pattern);
return this;
}
@Override
public Canvas setLineCap(LineCap cap) {
currentState().setLineCap(cap);
return this;
}
@Override
public Canvas setLineJoin(LineJoin join) {
currentState().setLineJoin(join);
return this;
}
@Override
public Canvas setMiterLimit(float miter) {
currentState().setMiterLimit(miter);
return this;
}
@Override
public Canvas setStrokeColor(int color) {
currentState().setStrokeColor(color);
return this;
}
@Override
public Canvas setStrokeWidth(float strokeWidth) {
currentState().setStrokeWidth(strokeWidth);
return this;
}
@Override
public Image snapshot() {
Bitmap bitmap = ((AndroidImage) this.image).bitmap();
return new AndroidImage(gfx, image.scale(), bitmap.copy(
bitmap.getConfig(), false), "<canvas>");
}
@Override
public Canvas strokeCircle(float x, float y, float radius) {
canvas.drawCircle(x, y, radius, currentState().prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas strokePath(Path path) {
canvas.drawPath(((AndroidPath) path).path, currentState()
.prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas strokeRect(float x, float y, float width, float height) {
float left = x;
float top = y;
float right = left + width;
float bottom = top + height;
canvas.drawRect(left, top, right, bottom, currentState()
.prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas strokeRoundRect(float x, float y, float width, float height,
float radius) {
canvas.translate(x, y);
dstR.set(0, 0, width, height);
canvas.drawRoundRect(dstR, radius, radius, currentState()
.prepareStroke());
canvas.translate(-x, -y);
isDirty = true;
return this;
}
@Override
public Canvas strokeText(TextLayout layout, float x, float y) {
((AndroidTextLayout) layout).draw(canvas, x, y, currentState()
.prepareStroke());
isDirty = true;
return this;
}
@Override
public Canvas transform(float m11, float m12, float m21, float m22,
float dx, float dy) {
m.setValues(new float[] { m11, m21, dx, m12, m22, dy, 0, 0, 1 });
canvas.concat(m);
return this;
}
@Override
public Canvas translate(float x, float y) {
canvas.translate(x, y);
return this;
}
@Override
protected AndroidCanvas gc() {
return this;
}
private AndroidCanvasState currentState() {
return paintStack.peek();
}
}