/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.flat;
import javax.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.RectF;
/**
* Base class for border drawing operations (used by DrawImage and DrawBorder). Draws rectangular or
* rounded border along the rectangle, defined by the bounding box of the AbstractDrawCommand.
*/
/* package */ abstract class AbstractDrawBorder extends AbstractDrawCommand {
private static final Paint PAINT = new Paint(Paint.ANTI_ALIAS_FLAG);
private static final RectF TMP_RECT = new RectF();
private static final int BORDER_PATH_DIRTY = 1 << 0;
static {
PAINT.setStyle(Paint.Style.STROKE);
}
private int mSetPropertiesFlag;
private int mBorderColor = Color.BLACK;
private float mBorderWidth;
private float mBorderRadius;
private @Nullable Path mPathForBorderRadius;
public final void setBorderWidth(float borderWidth) {
mBorderWidth = borderWidth;
setFlag(BORDER_PATH_DIRTY);
}
public final float getBorderWidth() {
return mBorderWidth;
}
public void setBorderRadius(float borderRadius) {
mBorderRadius = borderRadius;
setFlag(BORDER_PATH_DIRTY);
}
public final float getBorderRadius() {
return mBorderRadius;
}
public final void setBorderColor(int borderColor) {
mBorderColor = borderColor;
}
public final int getBorderColor() {
return mBorderColor;
}
@Override
protected void onBoundsChanged() {
setFlag(BORDER_PATH_DIRTY);
}
protected final void drawBorders(Canvas canvas) {
if (mBorderWidth < 0.5f) {
return;
}
if (mBorderColor == 0) {
return;
}
PAINT.setColor(mBorderColor);
PAINT.setStrokeWidth(mBorderWidth);
PAINT.setPathEffect(getPathEffectForBorderStyle());
canvas.drawPath(getPathForBorderRadius(), PAINT);
}
protected final void updatePath(Path path, float correction) {
path.reset();
TMP_RECT.set(
getLeft() + correction,
getTop() + correction,
getRight() - correction,
getBottom() - correction);
path.addRoundRect(
TMP_RECT,
mBorderRadius,
mBorderRadius,
Path.Direction.CW);
}
protected @Nullable PathEffect getPathEffectForBorderStyle() {
return null;
}
protected final boolean isFlagSet(int mask) {
return (mSetPropertiesFlag & mask) == mask;
}
protected final void setFlag(int mask) {
mSetPropertiesFlag |= mask;
}
protected final void resetFlag(int mask) {
mSetPropertiesFlag &= ~mask;
}
protected final Path getPathForBorderRadius() {
if (isFlagSet(BORDER_PATH_DIRTY)) {
if (mPathForBorderRadius == null) {
mPathForBorderRadius = new Path();
}
updatePath(mPathForBorderRadius, mBorderWidth * 0.5f);
resetFlag(BORDER_PATH_DIRTY);
}
return mPathForBorderRadius;
}
}