Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bugs and Improve Native Rendering for Image, Circle and Shadow #1507

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions Source/Fuse.Controls.Native/Android/Java/ShadowDrawable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package com.fuse.android.graphics;

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class ShadowDrawable extends Drawable {

private final Context context;
private final Paint shadowPaint;
private int shadowColor;
private int offsetX;
private int offsetY;
private int size;
private float[] cornerRadius = {0,0,0,0,0,0,0,0};
private boolean isCircle = false;

public ShadowDrawable(Context context, int shadowColor, int offsetX, int offsetY, int size) {
this.context = context;
this.shadowColor = shadowColor;
this.offsetX = offsetX;
this.offsetY = offsetY;
this.size = size;
shadowPaint = new Paint();
shadowPaint.setColor(shadowColor);
if (size > 0)
shadowPaint.setMaskFilter(new BlurMaskFilter(convertDpToPx(this.size), BlurMaskFilter.Blur.NORMAL));
}

@Override
public void draw(@NonNull Canvas canvas) {
int count = canvas.save();
drawShadow(canvas);
canvas.restoreToCount(count);
}

@Override
public void setAlpha(int alpha) {
float result = ((alpha / 255f) * (Color.alpha(this.shadowColor) / 255f)) * 255f;
shadowPaint.setAlpha((int)result);
invalidateSelf();
}

@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
shadowPaint.setColorFilter(colorFilter);
invalidateSelf();
}

@Override
public int getOpacity() {
int alpha = shadowPaint.getAlpha();
if (alpha == 255)
return PixelFormat.OPAQUE;
else if (alpha >= 1 && alpha <= 254)
return PixelFormat.TRANSLUCENT;
return PixelFormat.TRANSPARENT;
}

public void setColor(int color) {
if (color != getColor()) {
this.shadowColor = color;
shadowPaint.setColor(color);
invalidateSelf();
}
}

public int getColor() {
return this.shadowColor;
}

public void setSize(int size) {
if (size != getSize()) {
this.size = size;
if (size > 0)
shadowPaint.setMaskFilter(new BlurMaskFilter(convertDpToPx(this.size), BlurMaskFilter.Blur.NORMAL));
invalidateSelf();
}
}

public int getSize() {
return this.size;
}

public void setOffsetX(int offsetX) {
if (offsetX != getOffsetX()) {
this.offsetX = offsetX;
invalidateSelf();
}
}

public int getOffsetX() {
return this.offsetX;
}

public void setOffsetY(int offsetY) {
if (offsetY != getOffsetY()) {
this.offsetY = offsetY;
invalidateSelf();
}
}

public int getOffsetY() {
return this.offsetY;
}

private void drawShadow(Canvas canvas) {
Path shadowPath;
if (this.isCircle) {
shadowPath = new Path();
Rect bounds= getBounds();
float x = ((float) bounds.width() / 2) + this.offsetX;
float y = ((float) bounds.width() / 2) + this.offsetY;
float radius = ((float) bounds.width() / 2) + this.size;
shadowPath.addCircle(x, y, radius, Path.Direction.CW);
} else {
shadowPath = new Path();
int spreadExtent = size;
RectF shadowRect = new RectF(getBounds());
shadowRect.inset(-spreadExtent, -spreadExtent);
shadowRect.offset(offsetX, offsetY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
RectF subpixelInsetBounds = new RectF(getBounds());
subpixelInsetBounds.inset(0.4f, 0.4f);
Path clipPath = new Path();
clipPath.addRoundRect(subpixelInsetBounds, this.cornerRadius,
Path.Direction.CW);
canvas.clipOutPath(clipPath);
}
shadowPath.addRoundRect(shadowRect, this.cornerRadius, Path.Direction.CW);
}
canvas.drawPath(shadowPath, shadowPaint);
}

private int convertDpToPx(int dp) {
float density = context.getResources().getDisplayMetrics().density;
return Math.round(dp * density);
}

public void setCircle(boolean circle) {
this.isCircle = circle;
invalidateSelf();
}

public void setCornerRadius(float[] cornerRadius) {
this.cornerRadius[0] = cornerRadius[0] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[1] = cornerRadius[0] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[2] = cornerRadius[1] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[3] = cornerRadius[1] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[4] = cornerRadius[2] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[5] = cornerRadius[2] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[6] = cornerRadius[3] * context.getResources().getDisplayMetrics().density;
this.cornerRadius[7] = cornerRadius[3] * context.getResources().getDisplayMetrics().density;
invalidateSelf();
}
}
3 changes: 2 additions & 1 deletion Source/Fuse.Controls.Native/Fuse.Controls.Native.unoproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"Android/Java/ViewGroup.java:java:Android",
"Android/Java/CanvasViewGroup.java:java:Android",
"Android/Java/VideoView.java:java:Android",
"Android/Java/ScalableType.java:java:Android"
"Android/Java/ScalableType.java:java:Android",
"Android/Java/ShadowDrawable.java:java:Android"
]
}
7 changes: 5 additions & 2 deletions Source/Fuse.Controls.Native/iOS/ImageView.uno
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,11 @@ namespace Fuse.Controls.Native.iOS

public void UpdateImageTransform(float density, float2 origin, float2 scale, float2 drawSize)
{
// Set UIImageVIew size from drawSize param and avoid the use of Matrix Transformation
SetBounds(_uiImageView, 0.0f, 0.0f, drawSize.X, drawSize.Y);
SetTransform(_uiImageView, float4x4.Identity);
var imageSize = GetImageSize();
SetBounds(_uiImageView, 0.0f, 0.0f, imageSize.X, imageSize.Y);
var imageTransform = Matrix.Compose(float3(scale, 0.0f), float4.Identity, float3(origin, 0.0f));
SetTransform(_uiImageView, imageTransform);
}

static void SetTransform(ObjC.Object handle, float4x4 t)
Expand Down
10 changes: 5 additions & 5 deletions Source/Fuse.Controls.Panels/Panel.uno
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ namespace Fuse.Controls

void OnColorChanged(float4 value, IPropertyListener origin)
{
OnPropertyChanged(ColorPropertyName, origin as IPropertyListener);

if (!(Background is SolidColor))
Background = new SolidColor(value);
else
((SolidColor)Background).Color = value;
Background = new SolidColor(value);
else
((SolidColor)Background).Color = value;

OnPropertyChanged(ColorPropertyName, origin as IPropertyListener);
}

void ISurfaceDrawable.Draw(Surface surface) { ISurfaceDrawableDraw(surface); }
Expand Down
Loading