-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create BufferedImageGraphics2D to make BufferedImage drawable
- v3.2.0-testing3
- v3.2.0-testing2
- v2.5.3-release
- untagged-f2aff1dc9d5f8f2f68bb
- untagged-ee405fbd461a77c751ab
- untagged-e6692cc585bd72258bd2
- untagged-e704f5d227083304582d
- untagged-e1a9b9638594e949e7dd
- untagged-d229543fd6acea517aeb
- untagged-d7810f621136906a3bbe
- untagged-d67d434769a01163a7c5
- untagged-cd02aad81387e0bdf235
- untagged-c87d0cd2bd7100574166
- untagged-a59287e89e1347dc2890
- untagged-a9b6d0f2225cfc22834c
- untagged-99141368a81fdcedafc0
- untagged-650888f0f9b5ab6f7916
- untagged-83455b18c6a082b144d3
- untagged-704cd623172a535debc9
- untagged-130ed77f3e26cc9d0611
- untagged-75c2b96ddc3902297459
- untagged-23e8b4acc4135998d84c
- untagged-9fc5b486663c9b016525
- untagged-5f74ed4a6f2f2543a936
- untagged-4e188dc350729b642bd1
- untagged-4e80a0c1513abab0c480
- untagged-3b35c1aa66e7440e912f
- untagged-2c3f571a4eeac436e4c1
- untagged-1fd8f88190d83951261a
- untagged-1aee3fd0379eb9678d7b
- untagged-0b061ec748e3dedeb750
1 parent
91108a7
commit f85860f
Showing
2 changed files
with
1,355 additions
and
3 deletions.
There are no files selected for viewing
1,350 changes: 1,350 additions & 0 deletions
1,350
app/src/main/java/com/android/internal/awt/BufferedImageGraphics2D.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,1350 @@ | ||
/* | ||
* Copyright 2007, The Android Open Source Project | ||
* | ||
* 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. | ||
*/ | ||
|
||
package com.android.internal.awt; | ||
|
||
import com.android.internal.awt.AndroidGraphicsConfiguration; | ||
// import com.android.internal.graphics.NativeUtils; | ||
|
||
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.Graphics; | ||
import java.awt.Graphics2D; | ||
import java.awt.GraphicsConfiguration; | ||
import java.awt.Image; | ||
import java.awt.Polygon; | ||
import java.awt.Rectangle; | ||
import java.awt.RenderingHints; | ||
import java.awt.Shape; | ||
import java.awt.Stroke; | ||
import java.awt.font.FontRenderContext; | ||
import java.awt.font.GlyphVector; | ||
import java.awt.geom.AffineTransform; | ||
import java.awt.geom.Area; | ||
import java.awt.geom.GeneralPath; | ||
import java.awt.geom.NoninvertibleTransformException; | ||
import java.awt.geom.PathIterator; | ||
import java.awt.image.AffineTransformOp; | ||
import java.awt.image.BufferedImage; | ||
import java.awt.image.BufferedImageOp; | ||
import java.awt.image.DataBuffer; | ||
import java.awt.image.DirectColorModel; | ||
import java.awt.image.ImageObserver; | ||
import java.awt.image.Raster; | ||
import java.awt.image.RenderedImage; | ||
import java.awt.image.SinglePixelPackedSampleModel; | ||
import java.awt.image.WritableRaster; | ||
import java.awt.image.renderable.RenderableImage; | ||
import java.text.AttributedCharacterIterator; | ||
import java.util.Map; | ||
|
||
import org.apache.harmony.awt.gl.ImageSurface; | ||
import org.apache.harmony.awt.gl.MultiRectArea; | ||
import org.apache.harmony.awt.gl.Surface; | ||
import org.apache.harmony.awt.gl.font.AndroidGlyphVector; | ||
import org.apache.harmony.awt.gl.font.FontMetricsImpl; | ||
import org.apache.harmony.awt.gl.image.OffscreenImage; | ||
|
||
import android.graphics.Bitmap; | ||
import android.graphics.Canvas; | ||
import android.graphics.Matrix; | ||
import android.graphics.Paint; | ||
import android.graphics.Path; | ||
|
||
import android.graphics.Rect; | ||
import android.graphics.RectF; | ||
import android.graphics.Region; | ||
import android.graphics.Typeface; | ||
import android.graphics.PixelXorXfermode; | ||
import android.view.Display; | ||
import android.view.WindowManager; | ||
import android.content.Context; | ||
|
||
public class BufferedImageGraphics2D extends Graphics2D { | ||
|
||
private int displayWidth, displayHeight; | ||
|
||
protected Surface dstSurf = null; | ||
protected MultiRectArea clip = null; | ||
|
||
protected Composite composite = AlphaComposite.SrcOver; | ||
protected AffineTransform transform = new AffineTransform(); | ||
|
||
private Bitmap mB; | ||
private Canvas mC; | ||
|
||
// Android Paint | ||
public Paint mP; | ||
|
||
private java.awt.Font mFnt; | ||
|
||
// Cached Matrix | ||
public Matrix mM; | ||
private FontMetrics mFm; | ||
private RenderingHints mRh; | ||
private Color mBc; | ||
private BufferedImage mImg; | ||
|
||
private Area mCurrClip; | ||
|
||
public final static double RAD_360 = Math.PI / 180 * 360; | ||
|
||
// Image drawing | ||
private AndroidJavaBlitter blitter; | ||
private DirectColorModel cm; | ||
private SinglePixelPackedSampleModel sm; | ||
private WritableRaster wr; | ||
|
||
|
||
public static BufferedImageGraphics2D getInstance(BufferedImage img, Paint p) { | ||
if (img == null) { | ||
throw new RuntimeException( | ||
"Illegal argument, BufferedImage cannot be null!"); | ||
} | ||
return new BufferedImageGraphics2D(img, p); | ||
} | ||
|
||
private BufferedImageGraphics2D(BufferedImage img, Paint p) { | ||
super(); | ||
displayWidth = img.getWidth(); | ||
displayHeight = img.getHeight(); | ||
mB = Bitmap.createBitmap(displayWidth, displayHeight, Bitmap.Config.ARGB_8888); | ||
mC = new Canvas(mB); | ||
mP = p; | ||
mM = new Matrix(); | ||
mM.reset(); | ||
mM = mC.getMatrix(); | ||
mImg = img; | ||
Rect r = mC.getClipBounds(); | ||
int cl[] = {-1, r.top, r.left, -2, r.top, r.right, -2, r.bottom, r.right, -2, r.bottom, r.left}; | ||
mCurrClip = new Area(createShape(cl)); | ||
blitter = new AndroidJavaBlitter(mC); | ||
cm = new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000); | ||
sm = new SinglePixelPackedSampleModel( | ||
DataBuffer.TYPE_INT, displayWidth, displayHeight, cm.getMasks()); | ||
wr = Raster.createWritableRaster(sm, null); | ||
dstSurf = new ImageSurface(cm, wr); | ||
} | ||
|
||
@Override | ||
public void addRenderingHints(Map<?, ?> hints) { | ||
if (mRh == null) { | ||
mRh = (RenderingHints) hints; | ||
} | ||
mRh.add((RenderingHints) hints); | ||
} | ||
|
||
public float[] getMatrix() { | ||
float[] f = new float[9]; | ||
mC.getMatrix().getValues(f); | ||
return f; | ||
} | ||
|
||
/** | ||
* | ||
* @return a Matrix in Android format | ||
*/ | ||
public float[] getInverseMatrix() { | ||
AffineTransform af = new AffineTransform(createAWTMatrix(getMatrix())); | ||
try { | ||
af = af.createInverse(); | ||
} catch (NoninvertibleTransformException e) { | ||
} | ||
return createMatrix(af); | ||
} | ||
|
||
private Path getPath(Shape s) { | ||
Path path = new Path(); | ||
PathIterator pi = s.getPathIterator(null); | ||
while (pi.isDone() == false) { | ||
getCurrentSegment(pi, path); | ||
pi.next(); | ||
} | ||
return path; | ||
} | ||
|
||
private void getCurrentSegment(PathIterator pi, Path path) { | ||
float[] coordinates = new float[6]; | ||
int type = pi.currentSegment(coordinates); | ||
switch (type) { | ||
case PathIterator.SEG_MOVETO: | ||
path.moveTo(coordinates[0], coordinates[1]); | ||
break; | ||
case PathIterator.SEG_LINETO: | ||
path.lineTo(coordinates[0], coordinates[1]); | ||
break; | ||
case PathIterator.SEG_QUADTO: | ||
path.quadTo(coordinates[0], coordinates[1], coordinates[2], | ||
coordinates[3]); | ||
break; | ||
case PathIterator.SEG_CUBICTO: | ||
path.cubicTo(coordinates[0], coordinates[1], coordinates[2], | ||
coordinates[3], coordinates[4], coordinates[5]); | ||
break; | ||
case PathIterator.SEG_CLOSE: | ||
path.close(); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
private Shape createShape(int[] arr) { | ||
Shape s = new GeneralPath(); | ||
for(int i = 0; i < arr.length; i++) { | ||
int type = arr[i]; | ||
switch (type) { | ||
case -1: | ||
//MOVETO | ||
((GeneralPath)s).moveTo(arr[++i], arr[++i]); | ||
break; | ||
case -2: | ||
//LINETO | ||
((GeneralPath)s).lineTo(arr[++i], arr[++i]); | ||
break; | ||
case -3: | ||
//QUADTO | ||
((GeneralPath)s).quadTo(arr[++i], arr[++i], arr[++i], | ||
arr[++i]); | ||
break; | ||
case -4: | ||
//CUBICTO | ||
((GeneralPath)s).curveTo(arr[++i], arr[++i], arr[++i], | ||
arr[++i], arr[++i], arr[++i]); | ||
break; | ||
case -5: | ||
//CLOSE | ||
return s; | ||
default: | ||
break; | ||
} | ||
} | ||
return s; | ||
} | ||
/* | ||
public int[] getPixels() { | ||
return mC.getPixels(); | ||
}*/ | ||
|
||
public static float getRadian(float degree) { | ||
return (float) ((Math.PI / 180) * degree); | ||
} | ||
|
||
private Shape getShape() { | ||
return null; | ||
} | ||
|
||
public static float getDegree(float radian) { | ||
return (float) ((180 / Math.PI) * radian); | ||
} | ||
|
||
/* | ||
* Degree in radian | ||
*/ | ||
public static float getEllipsisX(float degree, float princAxis) { | ||
return (float) Math.cos(degree) * princAxis; | ||
} | ||
|
||
public static float getEllipsisY(float degree, float conAxis) { | ||
return (float) Math.sin(degree) * conAxis; | ||
} | ||
|
||
@Override | ||
public void clip(Shape s) { | ||
mC.clipPath(getPath(s)); | ||
} | ||
|
||
public void setCanvas(Canvas c) { | ||
mC = c; | ||
} | ||
|
||
@Override | ||
public void draw(Shape s) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.STROKE); | ||
mC.drawPath(getPath(s), mP); | ||
mP.setStyle(tmp); | ||
} | ||
/* | ||
private ArrayList getSegments(Shape s) { | ||
ArrayList arr = new ArrayList(); | ||
PathIterator pi = s.getPathIterator(null); | ||
while (pi.isDone() == false) { | ||
getCurrentSegment(pi, arr); | ||
pi.next(); | ||
} | ||
return arr; | ||
} | ||
private void getCurrentSegment(PathIterator pi, ArrayList arr) { | ||
float[] coordinates = new float[6]; | ||
int type = pi.currentSegment(coordinates); | ||
switch (type) { | ||
case PathIterator.SEG_MOVETO: | ||
arr.add(new Integer(-1)); | ||
break; | ||
case PathIterator.SEG_LINETO: | ||
arr.add(new Integer(-2)); | ||
break; | ||
case PathIterator.SEG_QUADTO: | ||
arr.add(new Integer(-3)); | ||
break; | ||
case PathIterator.SEG_CUBICTO: | ||
arr.add(new Integer(-4)); | ||
break; | ||
case PathIterator.SEG_CLOSE: | ||
arr.add(new Integer(-5)); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
*/ | ||
/* | ||
* Convenience method, not standard AWT | ||
*/ | ||
public void draw(Path s) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.STROKE); | ||
s.transform(mM); | ||
mC.drawPath(s, mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void drawGlyphVector(GlyphVector g, float x, float y) { | ||
// TODO draw at x, y | ||
// draw(g.getOutline()); | ||
/* | ||
Matrix matrix = new Matrix(); | ||
matrix.setTranslate(x, y); | ||
Path pth = getPath(g.getOutline()); | ||
pth.transform(matrix); | ||
draw(pth); | ||
*/ | ||
Path path = new Path(); | ||
char[] c = ((AndroidGlyphVector)g).getGlyphs(); | ||
mP.getTextPath(c, 0, c.length, x, y, path); | ||
mC.drawPath(path, mP); | ||
} | ||
|
||
@Override | ||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) { | ||
throw new RuntimeException("Not implemented!"); | ||
} | ||
|
||
@Override | ||
public void drawRenderedImage(RenderedImage img, AffineTransform xform) { | ||
throw new RuntimeException("Not implemented!"); | ||
} | ||
|
||
@Override | ||
public void drawString(AttributedCharacterIterator iterator, float x, | ||
float y) { | ||
throw new RuntimeException("AttributedCharacterIterator not supported!"); | ||
|
||
} | ||
|
||
@Override | ||
public void drawString(AttributedCharacterIterator iterator, int x, int y) { | ||
throw new RuntimeException("AttributedCharacterIterator not supported!"); | ||
|
||
} | ||
|
||
@Override | ||
public void drawString(String s, float x, float y) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
|
||
mP.setStyle(Paint.Style.FILL); | ||
Path pth = new Path(); | ||
mP.getTextPath(s, 0, s.length(), x, y, pth); | ||
mC.drawPath(pth, mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void drawString(String str, int x, int y) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStrokeWidth(0); | ||
|
||
mC.drawText(str.toCharArray(), 0, str.toCharArray().length, x, y, | ||
mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void fill(Shape s) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.FILL); | ||
mC.drawPath(getPath(s), mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public Color getBackground() { | ||
return mBc; | ||
} | ||
|
||
@Override | ||
public Composite getComposite() { | ||
throw new RuntimeException("Composite not implemented!"); | ||
} | ||
|
||
@Override | ||
public GraphicsConfiguration getDeviceConfiguration() { | ||
return new AndroidGraphicsConfiguration(); | ||
} | ||
|
||
@Override | ||
public FontRenderContext getFontRenderContext() { | ||
return new FontRenderContext(getTransform(), mP.isAntiAlias(), true); | ||
} | ||
|
||
@Override | ||
public java.awt.Paint getPaint() { | ||
throw new RuntimeException("AWT Paint not implemented in Android!"); | ||
} | ||
|
||
public Canvas getAndroidCanvas() { | ||
return mC; | ||
} | ||
|
||
public Paint getAndroidPaint() { | ||
return mP; | ||
} | ||
|
||
@Override | ||
public RenderingHints getRenderingHints() { | ||
return mRh; | ||
} | ||
|
||
@Override | ||
public Stroke getStroke() { | ||
if (mP != null) { | ||
return new BasicStroke(mP.getStrokeWidth(), mP.getStrokeCap() | ||
.ordinal(), mP.getStrokeJoin().ordinal()); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public AffineTransform getTransform() { | ||
return new AffineTransform(createAWTMatrix(getMatrix())); | ||
} | ||
|
||
@Override | ||
public boolean hit(Rectangle rect, Shape s, boolean onStroke) { | ||
// ???AWT TODO check if on stroke | ||
return s.intersects(rect.getX(), rect.getY(), rect.getWidth(), rect | ||
.getHeight()); | ||
} | ||
|
||
@Override | ||
public void rotate(double theta) { | ||
mM.preRotate((float) BufferedImageGraphics2D | ||
.getDegree((float) (RAD_360 - theta))); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void rotate(double theta, double x, double y) { | ||
mM.preRotate((float) BufferedImageGraphics2D.getDegree((float) theta), | ||
(float) x, (float) y); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void scale(double sx, double sy) { | ||
mM.setScale((float) sx, (float) sy); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void setBackground(Color color) { | ||
mBc = color; | ||
mC.clipRect(new Rect(0, 0, mC.getWidth(), mC.getHeight())); | ||
// TODO don't limit to current clip | ||
mC.drawARGB(color.getAlpha(), color.getRed(), color.getGreen(), color | ||
.getBlue()); | ||
} | ||
|
||
@Override | ||
public void setComposite(Composite comp) { | ||
throw new RuntimeException("Composite not implemented!"); | ||
} | ||
|
||
public void setSpaint(Paint paint) { | ||
mP = paint; | ||
} | ||
|
||
@Override | ||
public void setPaint(java.awt.Paint paint) { | ||
setColor((Color)paint); | ||
} | ||
|
||
@Override | ||
public Object getRenderingHint(RenderingHints.Key key) { | ||
if (mRh == null) { | ||
return null; | ||
} | ||
return mRh.get(key); | ||
} | ||
|
||
@Override | ||
public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { | ||
if (mRh == null) { | ||
mRh = new RenderingHints(hintKey, hintValue); | ||
} else { | ||
mRh.put(hintKey, hintValue); | ||
} | ||
applyHints(); | ||
} | ||
|
||
@Override | ||
public void setRenderingHints(Map<?, ?> hints) { | ||
mRh = (RenderingHints) hints; | ||
applyHints(); | ||
} | ||
|
||
private void applyHints() { | ||
Object o; | ||
|
||
// TODO do something like this: | ||
/* | ||
* Set s = mRh.keySet(); Iterator it = s.iterator(); while(it.hasNext()) { | ||
* o = it.next(); } | ||
*/ | ||
|
||
// ///////////////////////////////////////////////////////////////////// | ||
// not supported in skia | ||
/* | ||
* o = mRh.get(RenderingHints.KEY_ALPHA_INTERPOLATION); if | ||
* (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) { } else | ||
* if (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) { } | ||
* else if (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_COLOR_RENDERING); if | ||
* (o.equals(RenderingHints.VALUE_COLOR_RENDER_DEFAULT)) { } else if | ||
* (o.equals(RenderingHints.VALUE_COLOR_RENDER_QUALITY)) { } else if | ||
* (o.equals(RenderingHints.VALUE_COLOR_RENDER_SPEED)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_DITHERING); if | ||
* (o.equals(RenderingHints.VALUE_DITHER_DEFAULT)) { } else if | ||
* (o.equals(RenderingHints.VALUE_DITHER_DISABLE)) { } else if | ||
* (o.equals(RenderingHints.VALUE_DITHER_ENABLE)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_FRACTIONALMETRICS); if | ||
* (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT)) { } else | ||
* if (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_OFF)) { } else if | ||
* (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_ON)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_INTERPOLATION); if | ||
* (o.equals(RenderingHints.VALUE_INTERPOLATION_BICUBIC)) { } else if | ||
* (o.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) { } else if | ||
* (o .equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_RENDERING); if | ||
* (o.equals(RenderingHints.VALUE_RENDER_DEFAULT)) { } else if | ||
* (o.equals(RenderingHints.VALUE_RENDER_QUALITY)) { } else if | ||
* (o.equals(RenderingHints.VALUE_RENDER_SPEED)) { } | ||
* | ||
* o = mRh.get(RenderingHints.KEY_STROKE_CONTROL); if | ||
* (o.equals(RenderingHints.VALUE_STROKE_DEFAULT)) { } else if | ||
* (o.equals(RenderingHints.VALUE_STROKE_NORMALIZE)) { } else if | ||
* (o.equals(RenderingHints.VALUE_STROKE_PURE)) { } | ||
*/ | ||
|
||
o = mRh.get(RenderingHints.KEY_ANTIALIASING); | ||
if (o != null) { | ||
if (o.equals(RenderingHints.VALUE_ANTIALIAS_DEFAULT)) { | ||
mP.setAntiAlias(false); | ||
} else if (o.equals(RenderingHints.VALUE_ANTIALIAS_OFF)) { | ||
mP.setAntiAlias(false); | ||
} else if (o.equals(RenderingHints.VALUE_ANTIALIAS_ON)) { | ||
mP.setAntiAlias(true); | ||
} | ||
} | ||
|
||
o = mRh.get(RenderingHints.KEY_TEXT_ANTIALIASING); | ||
if (o != null) { | ||
if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT)) { | ||
mP.setAntiAlias(false); | ||
} else if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) { | ||
mP.setAntiAlias(false); | ||
} else if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) { | ||
mP.setAntiAlias(true); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void setStroke(Stroke s) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
BasicStroke bs = (BasicStroke) s; | ||
mP.setStyle(Paint.Style.STROKE); | ||
mP.setStrokeWidth(bs.getLineWidth()); | ||
|
||
int cap = bs.getEndCap(); | ||
if (cap == 0) { | ||
mP.setStrokeCap(Paint.Cap.BUTT); | ||
} else if (cap == 1) { | ||
mP.setStrokeCap(Paint.Cap.ROUND); | ||
} else if (cap == 2) { | ||
mP.setStrokeCap(Paint.Cap.SQUARE); | ||
} | ||
|
||
int join = bs.getLineJoin(); | ||
if (join == 0) { | ||
mP.setStrokeJoin(Paint.Join.MITER); | ||
} else if (join == 1) { | ||
mP.setStrokeJoin(Paint.Join.ROUND); | ||
} else if (join == 2) { | ||
mP.setStrokeJoin(Paint.Join.BEVEL); | ||
} | ||
} | ||
|
||
public static float[] createMatrix(AffineTransform Tx) { | ||
double[] at = new double[9]; | ||
Tx.getMatrix(at); | ||
float[] f = new float[at.length]; | ||
f[0] = (float) at[0]; | ||
f[1] = (float) at[2]; | ||
f[2] = (float) at[4]; | ||
f[3] = (float) at[1]; | ||
f[4] = (float) at[3]; | ||
f[5] = (float) at[5]; | ||
f[6] = 0; | ||
f[7] = 0; | ||
f[8] = 1; | ||
return f; | ||
} | ||
|
||
private float[] createAWTMatrix(float[] matrix) { | ||
float[] at = new float[9]; | ||
at[0] = matrix[0]; | ||
at[1] = matrix[3]; | ||
at[2] = matrix[1]; | ||
at[3] = matrix[4]; | ||
at[4] = matrix[2]; | ||
at[5] = matrix[5]; | ||
at[6] = 0; | ||
at[7] = 0; | ||
at[8] = 1; | ||
return at; | ||
} | ||
|
||
public static Matrix createMatrixObj(AffineTransform Tx) { | ||
Matrix m = new Matrix(); | ||
m.reset(); | ||
m.setValues(createMatrix(Tx)); | ||
return m; | ||
} | ||
|
||
@Override | ||
public void setTransform(AffineTransform Tx) { | ||
mM.reset(); | ||
/* | ||
* if(Tx.isIdentity()) { mM = new Matrix(); } | ||
*/ | ||
mM.setValues(createMatrix(Tx)); | ||
Matrix m = new Matrix(); | ||
m.setValues(getInverseMatrix()); | ||
mC.concat(m); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void shear(double shx, double shy) { | ||
mM.setSkew((float) shx, (float) shy); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void transform(AffineTransform Tx) { | ||
Matrix m = new Matrix(); | ||
m.setValues(createMatrix(Tx)); | ||
mC.concat(m); | ||
} | ||
|
||
@Override | ||
public void translate(double tx, double ty) { | ||
mM.setTranslate((float) tx, (float) ty); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void translate(int x, int y) { | ||
mM.setTranslate((float) x, (float) y); | ||
mC.concat(mM); | ||
} | ||
|
||
@Override | ||
public void clearRect(int x, int y, int width, int height) { | ||
mC.clipRect(x, y, x + width, y + height); | ||
if (mBc != null) { | ||
mC.drawARGB(mBc.getAlpha(), mBc.getBlue(), mBc.getGreen(), mBc | ||
.getRed()); | ||
} else { | ||
mC.drawARGB(0xff, 0xff, 0xff, 0xff); | ||
} | ||
} | ||
|
||
@Override | ||
public void clipRect(int x, int y, int width, int height) { | ||
int cl[] = {-1, x, y, -2, x, y + width, -2, x + height, y + width, -2, x + height, y}; | ||
Shape shp = createShape(cl); | ||
mCurrClip.intersect(new Area(shp)); | ||
mC.clipRect(new Rect(x, y, x + width, y + height), Region.Op.INTERSECT); | ||
} | ||
|
||
@Override | ||
public void copyArea(int sx, int sy, int width, int height, int dx, int dy) { | ||
copyArea(mC, sx, sy, width + dx, height + dy, dx, dy); | ||
} | ||
|
||
@Override | ||
public Graphics create() { | ||
return this; | ||
} | ||
|
||
@Override | ||
public void dispose() { | ||
int[] pixels = new int[displayWidth * displayHeight]; | ||
mB.getPixels(pixels, 0, displayWidth, 0, 0, displayWidth, displayHeight); | ||
mImg.setRGB(0, 0, displayWidth, displayHeight, pixels, 0, displayWidth); | ||
|
||
mC = null; | ||
mP = null; | ||
} | ||
|
||
@Override | ||
public void drawArc(int x, int y, int width, int height, int sa, int ea) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mP.setStrokeWidth(0); | ||
mC.drawArc(new RectF(x, y, x + width, y + height), 360 - (ea + sa), | ||
ea, true, mP); | ||
} | ||
|
||
|
||
// ???AWT: only used for debuging, delete in final version | ||
public void drawBitmap(Bitmap bm, float x, float y, Paint p) { | ||
mC.drawBitmap(bm, x, y, null); | ||
} | ||
|
||
@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 (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mC.drawLine(x1, y1, x2, y2, mP); | ||
} | ||
|
||
@Override | ||
public void drawOval(int x, int y, int width, int height) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mP.setStyle(Paint.Style.STROKE); | ||
mC.drawOval(new RectF(x, y, x + width, y + height), mP); | ||
} | ||
|
||
@Override | ||
public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mC.drawLine(xpoints[npoints - 1], ypoints[npoints - 1], xpoints[0], | ||
ypoints[0], mP); | ||
for (int i = 0; i < npoints - 1; i++) { | ||
mC.drawLine(xpoints[i], ypoints[i], xpoints[i + 1], | ||
ypoints[i + 1], mP); | ||
} | ||
} | ||
|
||
@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 drawRoundRect(int x, int y, int width, int height, | ||
int arcWidth, int arcHeight) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mC.drawRoundRect(new RectF(x, y, width, height), arcWidth, | ||
arcHeight, mP); | ||
} | ||
|
||
@Override | ||
public void fillArc(int x, int y, int width, int height, int sa, int ea) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
|
||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.FILL_AND_STROKE); | ||
mC.drawArc(new RectF(x, y, x + width, y + height), 360 - (sa + ea), | ||
ea, true, mP); | ||
|
||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void fillOval(int x, int y, int width, int height) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.FILL); | ||
mC.drawOval(new RectF(x, y, x + width, y + height), mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void fillPolygon(int[] xpoints, int[] ypoints, int npoints) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mC.save(); // (CLIP_SAVE_FLAG); | ||
|
||
mP.setStyle(Paint.Style.FILL); | ||
|
||
GeneralPath filledPolygon = new GeneralPath( | ||
GeneralPath.WIND_EVEN_ODD, npoints); | ||
filledPolygon.moveTo(xpoints[0], ypoints[0]); | ||
for (int index = 1; index < xpoints.length; index++) { | ||
filledPolygon.lineTo(xpoints[index], ypoints[index]); | ||
} | ||
filledPolygon.closePath(); | ||
Path path = getPath(filledPolygon); | ||
mC.clipPath(path); | ||
mC.drawPath(path, mP); | ||
|
||
mP.setStyle(tmp); | ||
mC.restore(); | ||
} | ||
|
||
@Override | ||
public void fillRect(int x, int y, int width, int height) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
Paint.Style tmp = mP.getStyle(); | ||
mP.setStyle(Paint.Style.FILL); | ||
mC.drawRect(new Rect(x, y, x + width, y + height), mP); | ||
mP.setStyle(tmp); | ||
} | ||
|
||
@Override | ||
public void drawRect(int x, int y, int width, int height) { | ||
int[] xpoints = { x, x, x + width, x + width }; | ||
int[] ypoints = { y, y + height, y + height, y }; | ||
drawPolygon(xpoints, ypoints, 4); | ||
} | ||
|
||
@Override | ||
public void fillRoundRect(int x, int y, int width, int height, | ||
int arcWidth, int arcHeight) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mP.setStyle(Paint.Style.FILL); | ||
mC.drawRoundRect(new RectF(x, y, x + width, y + height), arcWidth, | ||
arcHeight, mP); | ||
} | ||
|
||
@Override | ||
public Shape getClip() { | ||
return mCurrClip; | ||
} | ||
|
||
@Override | ||
public Rectangle getClipBounds() { | ||
Rect r = mC.getClipBounds(); | ||
return new Rectangle(r.left, r.top, r.width(), r.height()); | ||
} | ||
|
||
@Override | ||
public Color getColor() { | ||
if (mP != null) { | ||
return new Color(mP.getColor()); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Font getFont() { | ||
return mFnt; | ||
} | ||
|
||
@Override | ||
public FontMetrics getFontMetrics(Font font) { | ||
mFm = new FontMetricsImpl(font); | ||
return mFm; | ||
} | ||
|
||
@Override | ||
public void setClip(int x, int y, int width, int height) { | ||
int cl[] = {-1, x, y, -2, x, y + width, -2, x + height, y + width, -2, x + height, y}; | ||
mCurrClip = new Area(createShape(cl)); | ||
mC.clipRect(x, y, x + width, y + height, Region.Op.REPLACE); | ||
|
||
} | ||
|
||
@Override | ||
public void setClip(Shape clip) { | ||
mCurrClip = new Area(clip); | ||
mC.clipPath(getPath(clip), Region.Op.REPLACE); | ||
} | ||
|
||
@Override | ||
public void setColor(Color c) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
if (c == null) { | ||
c = Color.decode("#00000000"); | ||
} | ||
mP.setColor(c.getRGB()); | ||
} | ||
|
||
/** | ||
* Font mapping: | ||
* | ||
* Family: | ||
* | ||
* Android AWT | ||
* ------------------------------------- | ||
* serif Serif / TimesRoman | ||
* sans-serif SansSerif / Helvetica | ||
* monospace Monospaced / Courier | ||
* | ||
* Style: | ||
* | ||
* Android AWT | ||
* ------------------------------------- | ||
* normal Plain | ||
* bold bold | ||
* italic italic | ||
* | ||
*/ | ||
@Override | ||
public void setFont(Font font) { | ||
if (font == null) { | ||
return; | ||
} | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
|
||
mFnt = font; | ||
Typeface tf = null; | ||
int sty = font.getStyle(); | ||
String nam = font.getName(); | ||
String aF = ""; | ||
if (nam != null) { | ||
if (nam.equalsIgnoreCase("Serif") | ||
|| nam.equalsIgnoreCase("TimesRoman")) { | ||
aF = "serif"; | ||
} else if (nam.equalsIgnoreCase("SansSerif") | ||
|| nam.equalsIgnoreCase("Helvetica")) { | ||
aF = "sans-serif"; | ||
} else if (nam.equalsIgnoreCase("Monospaced") | ||
|| nam.equalsIgnoreCase("Courier")) { | ||
aF = "monospace"; | ||
} | ||
} | ||
|
||
switch (sty) { | ||
case Font.PLAIN: | ||
tf = Typeface.create(aF, Typeface.NORMAL); | ||
break; | ||
case Font.BOLD: | ||
tf = Typeface.create(aF, Typeface.BOLD); | ||
break; | ||
case Font.ITALIC: | ||
tf = Typeface.create(aF, Typeface.ITALIC); | ||
break; | ||
case Font.BOLD | Font.ITALIC: | ||
tf = Typeface.create(aF, Typeface.BOLD_ITALIC); | ||
break; | ||
default: | ||
tf = Typeface.DEFAULT; | ||
} | ||
|
||
mP.setTextSize(font.getSize()); | ||
mP.setTypeface(tf); | ||
} | ||
|
||
@Override | ||
public void drawBytes(byte[] data, int offset, int length, int x, int y) { | ||
drawString(new String(data, offset, length), x, y); | ||
} | ||
|
||
@Override | ||
public void drawPolygon(Polygon p) { | ||
drawPolygon(p.xpoints, p.ypoints, p.npoints); | ||
} | ||
|
||
@Override | ||
public void fillPolygon(Polygon p) { | ||
fillPolygon(p.xpoints, p.ypoints, p.npoints); | ||
} | ||
|
||
@Override | ||
public Rectangle getClipBounds(Rectangle r) { | ||
Shape clip = getClip(); | ||
if (clip != null) { | ||
Rectangle b = clip.getBounds(); | ||
r.x = b.x; | ||
r.y = b.y; | ||
r.width = b.width; | ||
r.height = b.height; | ||
} | ||
return r; | ||
} | ||
|
||
@Override | ||
public boolean hitClip(int x, int y, int width, int height) { | ||
return getClipBounds().intersects(new Rectangle(x, y, width, height)); | ||
} | ||
|
||
@Override | ||
public void drawChars(char[] data, int offset, int length, int x, int y) { | ||
mC.drawText(data, offset, length, x, y, mP); | ||
} | ||
|
||
@Override | ||
public void setPaintMode() { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mP.setXfermode(null); | ||
} | ||
|
||
@Override | ||
public void setXORMode(Color color) { | ||
if (mP == null) { | ||
mP = new Paint(); | ||
} | ||
mP.setXfermode(new PixelXorXfermode(color.getRGB())); | ||
} | ||
|
||
@Override | ||
public void fill3DRect(int x, int y, int width, int height, boolean raised) { | ||
Color color = getColor(); | ||
Color colorUp, colorDown; | ||
if (raised) { | ||
colorUp = color.brighter(); | ||
colorDown = color.darker(); | ||
setColor(color); | ||
} else { | ||
colorUp = color.darker(); | ||
colorDown = color.brighter(); | ||
setColor(colorUp); | ||
} | ||
|
||
width--; | ||
height--; | ||
fillRect(x+1, y+1, width-1, height-1); | ||
|
||
setColor(colorUp); | ||
fillRect(x, y, width, 1); | ||
fillRect(x, y+1, 1, height); | ||
|
||
setColor(colorDown); | ||
fillRect(x+width, y, 1, height); | ||
fillRect(x+1, y+height, width, 1); | ||
} | ||
|
||
@Override | ||
public void draw3DRect(int x, int y, int width, int height, boolean raised) { | ||
Color color = getColor(); | ||
Color colorUp, colorDown; | ||
if (raised) { | ||
colorUp = color.brighter(); | ||
colorDown = color.darker(); | ||
} else { | ||
colorUp = color.darker(); | ||
colorDown = color.brighter(); | ||
} | ||
|
||
setColor(colorUp); | ||
fillRect(x, y, width, 1); | ||
fillRect(x, y+1, 1, height); | ||
|
||
setColor(colorDown); | ||
fillRect(x+width, y, 1, height); | ||
fillRect(x+1, y+height, width, 1); | ||
} | ||
|
||
public void copyArea(Canvas canvas, int sx, int sy, int width, int height, int dx, int dy) { | ||
sx += getTransform().getTranslateX(); | ||
sy += getTransform().getTranslateY(); | ||
|
||
// NativeUtils.nativeScrollRect(canvas, new Rect(sx, sy, sx + width, sy + height), dx, dy); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters