mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-19 14:20:22 +08:00
perf(android): reduce java object creation (#10129)
This commit is contained in:
Binary file not shown.
@ -17,6 +17,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@ -276,6 +277,44 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RectF backgroundBoundsF = new RectF();
|
||||
Path backgroundPath = new Path();
|
||||
RectF backgroundRect = new RectF();
|
||||
Paint backgroundColorPaint = new Paint();
|
||||
Path backgroundNoRepeatPath = new Path();
|
||||
Paint backgroundImagePaint = new Paint();
|
||||
Paint backgroundGradientPaint = new Paint();
|
||||
Paint borderPaint = new Paint();
|
||||
Path borderPath = new Path();
|
||||
RectF borderOuterRect = new RectF();
|
||||
RectF borderInnerRect = new RectF();
|
||||
|
||||
PointF lto = new PointF(); // left-top-outside
|
||||
PointF lti = new PointF(); // left-top-inside
|
||||
|
||||
PointF rto = new PointF(); // right-top-outside
|
||||
PointF rti = new PointF(); // right-top-outside
|
||||
|
||||
PointF rbo = new PointF(); // right-bottom-outside
|
||||
PointF rbi = new PointF(); // right-bottom-inside
|
||||
|
||||
PointF lbo = new PointF(); // left-bottom-outside
|
||||
PointF lbi = new PointF(); // left-bottom-inside
|
||||
|
||||
|
||||
Paint topBorderPaint = new Paint();
|
||||
Path topBorderPath = new Path();
|
||||
|
||||
Paint rightBorderPaint = new Paint();
|
||||
Path rightBorderPath = new Path();
|
||||
|
||||
Paint bottomBorderPaint = new Paint();
|
||||
Path bottomBorderPath = new Path();
|
||||
|
||||
Paint leftBorderPaint = new Paint();
|
||||
Path leftBorderPath = new Path();
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
Rect bounds = this.getBounds();
|
||||
@ -287,7 +326,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
return;
|
||||
}
|
||||
|
||||
RectF backgroundBoundsF = new RectF(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
backgroundBoundsF.set(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
|
||||
float topBackoffAntialias = calculateBackoffAntialias(this.borderTopColor, this.borderTopWidth);
|
||||
float rightBackoffAntialias = calculateBackoffAntialias(this.borderRightColor, this.borderRightWidth);
|
||||
@ -301,18 +340,18 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
Math.max(0, borderBottomLeftRadius + leftBackoffAntialias), Math.max(0, borderBottomLeftRadius + bottomBackoffAntialias)
|
||||
};
|
||||
|
||||
Path backgroundPath = new Path();
|
||||
RectF backgroundRect = new RectF(
|
||||
leftBackoffAntialias,
|
||||
backgroundPath.reset();
|
||||
|
||||
backgroundRect.set(leftBackoffAntialias,
|
||||
topBackoffAntialias,
|
||||
width - rightBackoffAntialias,
|
||||
height - bottomBackoffAntialias
|
||||
);
|
||||
height - bottomBackoffAntialias);
|
||||
|
||||
backgroundPath.addRoundRect(backgroundRect, backgroundRadii, Path.Direction.CW);
|
||||
|
||||
// draw background
|
||||
if (this.backgroundColor != 0) {
|
||||
Paint backgroundColorPaint = new Paint();
|
||||
backgroundColorPaint.reset();
|
||||
backgroundColorPaint.setStyle(Paint.Style.FILL);
|
||||
backgroundColorPaint.setColor(this.backgroundColor);
|
||||
backgroundColorPaint.setAntiAlias(true);
|
||||
@ -337,7 +376,9 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
transform.postTranslate(params.posX, params.posY);
|
||||
|
||||
Paint backgroundImagePaint = new Paint();
|
||||
|
||||
backgroundImagePaint.reset();
|
||||
|
||||
BitmapShader shader = new BitmapShader(
|
||||
this.backgroundBitmap,
|
||||
params.repeatX ? Shader.TileMode.REPEAT : Shader.TileMode.CLAMP,
|
||||
@ -358,7 +399,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
} else {
|
||||
boolean supportsPathOp = android.os.Build.VERSION.SDK_INT >= 19;
|
||||
if (supportsPathOp) {
|
||||
Path backgroundNoRepeatPath = new Path();
|
||||
backgroundNoRepeatPath.reset();
|
||||
backgroundNoRepeatPath.addRect(params.posX, params.posY, params.posX + imageWidth, params.posY + imageHeight, Path.Direction.CCW);
|
||||
intersect(backgroundNoRepeatPath, backgroundPath);
|
||||
canvas.drawPath(backgroundNoRepeatPath, backgroundImagePaint);
|
||||
@ -374,7 +415,9 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
|
||||
if (this.backgroundGradient != null) {
|
||||
LinearGradientDefinition def = this.backgroundGradient;
|
||||
Paint backgroundGradientPaint = new Paint();
|
||||
|
||||
backgroundGradientPaint.reset();
|
||||
|
||||
LinearGradient shader = new LinearGradient(
|
||||
def.getStartX() * width, def.getStartY() * height,
|
||||
def.getEndX() * width, def.getEndY() * height,
|
||||
@ -394,7 +437,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
if (this.clipPath != null && !this.clipPath.isEmpty()) {
|
||||
float borderWidth = this.getUniformBorderWidth();
|
||||
if (borderWidth > 0) {
|
||||
Paint borderPaint = new Paint();
|
||||
borderPaint.reset();
|
||||
borderPaint.setColor(this.getUniformBorderColor());
|
||||
borderPaint.setStyle(Paint.Style.STROKE);
|
||||
borderPaint.setStrokeWidth(borderWidth);
|
||||
@ -405,13 +448,15 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
} else if (this.hasUniformBorderColor()) {
|
||||
// iOS and browsers use black when no color is specified.
|
||||
if (borderLeftWidth > 0 || borderTopWidth > 0 || borderRightWidth > 0 || borderBottomWidth > 0) {
|
||||
Paint borderPaint = new Paint();
|
||||
borderPaint.reset();
|
||||
borderPaint.setColor(this.getUniformBorderColor());
|
||||
borderPaint.setStyle(Paint.Style.FILL);
|
||||
borderPaint.setAntiAlias(true);
|
||||
Path borderPath = new Path();
|
||||
|
||||
RectF borderOuterRect = new RectF(0, 0, width, height);
|
||||
borderPath.reset();
|
||||
|
||||
borderOuterRect.set(0, 0, width, height);
|
||||
|
||||
float[] borderOuterRadii = {
|
||||
borderTopLeftRadius, borderTopLeftRadius,
|
||||
borderTopRightRadius, borderTopRightRadius,
|
||||
@ -420,7 +465,7 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
};
|
||||
borderPath.addRoundRect(borderOuterRect, borderOuterRadii, Path.Direction.CW);
|
||||
|
||||
RectF borderInnerRect = new RectF(
|
||||
borderInnerRect.set(
|
||||
borderLeftWidth,
|
||||
borderTopWidth,
|
||||
width - borderRightWidth,
|
||||
@ -453,23 +498,25 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
// +---------------------+
|
||||
//lbo rbo
|
||||
|
||||
PointF lto = new PointF(0, 0); // left-top-outside
|
||||
PointF lti = new PointF(left, top); // left-top-inside
|
||||
lto.set(0, 0); // left-top-outside
|
||||
lti.set(left, top); // left-top-inside
|
||||
|
||||
PointF rto = new PointF(bounds.right, 0); // right-top-outside
|
||||
PointF rti = new PointF(bounds.right - right, top); // right-top-outside
|
||||
rto.set(bounds.right, 0); // right-top-outside
|
||||
rti.set(bounds.right - right, top); // right-top-outside
|
||||
|
||||
PointF rbo = new PointF(bounds.right, bounds.bottom); // right-bottom-outside
|
||||
PointF rbi = new PointF(bounds.right - right, bounds.bottom - bottom); // right-bottom-inside
|
||||
rbo.set(bounds.right, bounds.bottom); // right-bottom-outside
|
||||
rbi.set(bounds.right - right, bounds.bottom - bottom); // right-bottom-inside
|
||||
|
||||
lbo.set(0, bounds.bottom); // left-bottom-outside
|
||||
lbi.set(left, bounds.bottom - bottom); // left-bottom-inside
|
||||
|
||||
PointF lbo = new PointF(0, bounds.bottom); // left-bottom-outside
|
||||
PointF lbi = new PointF(left, bounds.bottom - bottom); // left-bottom-inside
|
||||
|
||||
if (this.borderTopWidth > 0) {
|
||||
Paint topBorderPaint = new Paint();
|
||||
topBorderPaint.reset();
|
||||
topBorderPaint.setColor(this.borderTopColor);
|
||||
topBorderPaint.setAntiAlias(true);
|
||||
Path topBorderPath = new Path();
|
||||
|
||||
topBorderPath.reset();
|
||||
topBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
topBorderPath.moveTo(lto.x, lto.y);
|
||||
topBorderPath.lineTo(rto.x, rto.y);
|
||||
@ -480,10 +527,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderRightWidth > 0) {
|
||||
Paint rightBorderPaint = new Paint();
|
||||
|
||||
rightBorderPaint.reset();
|
||||
rightBorderPaint.setColor(this.borderRightColor);
|
||||
rightBorderPaint.setAntiAlias(true);
|
||||
Path rightBorderPath = new Path();
|
||||
|
||||
rightBorderPath.reset();
|
||||
rightBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
rightBorderPath.moveTo(rto.x, rto.y);
|
||||
rightBorderPath.lineTo(rbo.x, rbo.y);
|
||||
@ -494,10 +543,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderBottomWidth > 0) {
|
||||
Paint bottomBorderPaint = new Paint();
|
||||
|
||||
bottomBorderPaint.reset();
|
||||
bottomBorderPaint.setColor(this.borderBottomColor);
|
||||
bottomBorderPaint.setAntiAlias(true);
|
||||
Path bottomBorderPath = new Path();
|
||||
|
||||
bottomBorderPath.reset();
|
||||
bottomBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
bottomBorderPath.moveTo(rbo.x, rbo.y);
|
||||
bottomBorderPath.lineTo(lbo.x, lbo.y);
|
||||
@ -508,10 +559,11 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
}
|
||||
|
||||
if (this.borderLeftWidth > 0) {
|
||||
Paint leftBorderPaint = new Paint();
|
||||
leftBorderPaint.reset();
|
||||
leftBorderPaint.setColor(this.borderLeftColor);
|
||||
leftBorderPaint.setAntiAlias(true);
|
||||
Path leftBorderPath = new Path();
|
||||
|
||||
leftBorderPath.reset();
|
||||
leftBorderPath.setFillType(Path.FillType.EVEN_ODD);
|
||||
leftBorderPath.moveTo(lbo.x, lbo.y);
|
||||
leftBorderPath.lineTo(lto.x, lto.y);
|
||||
@ -606,7 +658,12 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
top = cY - rY;
|
||||
right = (rX * 2) + left;
|
||||
bottom = (rY * 2) + top;
|
||||
canvas.drawOval(new RectF(left, top, right, bottom), paint);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
canvas.drawOval(left, top, right, bottom, paint);
|
||||
} else {
|
||||
canvas.drawOval(new RectF(left, top, right, bottom), paint);
|
||||
}
|
||||
break;
|
||||
case "polygon":
|
||||
Path path = new Path();
|
||||
@ -832,18 +889,31 @@ public class BorderDrawable extends ColorDrawable implements BitmapOwner {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
private final Path outlineBackgroundPath = new Path();
|
||||
private final RectF outlineRectF = new RectF();
|
||||
|
||||
@Override
|
||||
public void getOutline(@NonNull Outline outline) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
Path backgroundPath = new Path();
|
||||
outlineBackgroundPath.reset();
|
||||
float[] backgroundRadii = {
|
||||
Math.max(0, borderTopLeftRadius), Math.max(0, borderTopLeftRadius),
|
||||
Math.max(0, borderTopRightRadius), Math.max(0, borderTopRightRadius),
|
||||
Math.max(0, borderBottomRightRadius), Math.max(0, borderBottomRightRadius),
|
||||
Math.max(0, borderBottomLeftRadius), Math.max(0, borderBottomLeftRadius)
|
||||
};
|
||||
backgroundPath.addRoundRect(new RectF(getBounds()), backgroundRadii, Path.Direction.CW);
|
||||
outline.setConvexPath(backgroundPath);
|
||||
outlineRectF.setEmpty();
|
||||
outlineRectF.set(getBounds());
|
||||
backgroundPath.addRoundRect(outlineRectF, backgroundRadii, Path.Direction.CW);
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// see setConvexPath notes
|
||||
outline.setPath(backgroundPath);
|
||||
} else {
|
||||
outline.setConvexPath(backgroundPath);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new IllegalStateException("Method supported on API 21 or higher");
|
||||
}
|
||||
|
@ -8,10 +8,14 @@ import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
|
||||
import org.nativescript.widgets.image.BitmapOwner;
|
||||
@ -26,6 +30,7 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
|
||||
private final Path path = new Path();
|
||||
private final RectF rect = new RectF();
|
||||
private final Paint paint = new Paint();
|
||||
|
||||
private double scaleW = 1;
|
||||
private double scaleH = 1;
|
||||
@ -209,6 +214,8 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
}
|
||||
}
|
||||
|
||||
private boolean mSettingBitmap = false;
|
||||
|
||||
@Override
|
||||
public void setImageBitmap(Bitmap bm) {
|
||||
Fetcher fetcher = Fetcher.getInstance(this.getContext());
|
||||
@ -217,11 +224,75 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
if (mUseCache && mUri != null && mBitmap != null && fetcher != null) {
|
||||
fetcher.removeBitmap(mUri);
|
||||
}
|
||||
|
||||
mSettingBitmap = true;
|
||||
super.setImageBitmap(bm);
|
||||
this.mBitmap = bm;
|
||||
if (bm != null) {
|
||||
bitmapWidth = bm.getWidth();
|
||||
bitmapHeight = bm.getHeight();
|
||||
bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
} else {
|
||||
bitmapWidth = -1;
|
||||
bitmapHeight = -1;
|
||||
}
|
||||
mSettingBitmap = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(@Nullable Drawable drawable) {
|
||||
super.setImageDrawable(drawable);
|
||||
setBitmapShader();
|
||||
}
|
||||
|
||||
|
||||
private final Canvas canvas = new Canvas();
|
||||
private BitmapShader bitmapShader = null;
|
||||
private int bitmapWidth = -1;
|
||||
private int bitmapHeight = -1;
|
||||
|
||||
private void setBitmapShader() {
|
||||
if (mSettingBitmap) {
|
||||
return;
|
||||
}
|
||||
Bitmap mBitmap = null;
|
||||
Drawable drawable = getDrawable();
|
||||
if (drawable != null) {
|
||||
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
mBitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||
} else {
|
||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
|
||||
canvas.setBitmap(bitmap);
|
||||
Rect previousBounds = null;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
previousBounds = drawable.getBounds();
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
}
|
||||
|
||||
drawable.draw(canvas);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
drawable.setBounds(previousBounds);
|
||||
}
|
||||
mBitmap = bitmap;
|
||||
}
|
||||
} else {
|
||||
bitmapShader = null;
|
||||
}
|
||||
|
||||
if (mBitmap != null) {
|
||||
bitmapWidth = mBitmap.getWidth();
|
||||
bitmapHeight = mBitmap.getHeight();
|
||||
bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
} else {
|
||||
bitmapWidth = -1;
|
||||
bitmapHeight = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
BorderDrawable background = this.getBackground() instanceof BorderDrawable ? (BorderDrawable) this.getBackground() : null;
|
||||
@ -257,17 +328,21 @@ public class ImageView extends androidx.appcompat.widget.AppCompatImageView impl
|
||||
innerHeight = this.getHeight() - borderTopWidth - borderBottomWidth;
|
||||
|
||||
// TODO: Capture all created objects here in locals and update them instead...
|
||||
Path path = new Path();
|
||||
path.reset();
|
||||
paint.reset();
|
||||
|
||||
float[] radii = {
|
||||
Math.max(0, borderTopLeftRadius - borderLeftWidth), Math.max(0, borderTopLeftRadius - borderTopWidth),
|
||||
Math.max(0, borderTopRightRadius - borderRightWidth), Math.max(0, borderTopRightRadius - borderTopWidth),
|
||||
Math.max(0, borderBottomRightRadius - borderRightWidth), Math.max(0, borderBottomRightRadius - borderBottomWidth),
|
||||
Math.max(0, borderBottomLeftRadius - borderLeftWidth), Math.max(0, borderBottomLeftRadius - borderBottomWidth)
|
||||
};
|
||||
path.addRoundRect(new RectF(borderLeftWidth, borderTopWidth, borderLeftWidth + innerWidth, borderTopWidth + innerHeight), radii, Path.Direction.CW);
|
||||
|
||||
Paint paint = new Paint();
|
||||
BitmapShader bitmapShader = new BitmapShader(this.mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||
rect.setEmpty();
|
||||
rect.set(borderLeftWidth, borderTopWidth, borderLeftWidth + innerWidth, borderTopWidth + innerHeight);
|
||||
|
||||
path.addRoundRect(rect, radii, Path.Direction.CW);
|
||||
|
||||
|
||||
float bitmapWidth = (float) mBitmap.getWidth();
|
||||
float bitmapHeight = (float) mBitmap.getHeight();
|
||||
|
Reference in New Issue
Block a user