下面列出了怎么用android.graphics.Region.Op的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Returns a list of {@code Rect}s, each of which is the bounding rectangle for a non-functional
* area on the display.
*
* There will be at most one non-functional area per short edge of the device, and none on
* the long edges.
*
* @return a list of bounding {@code Rect}s, one for each display cutout area.
*/
public List<Rect> getBoundingRects() {
List<Rect> result = new ArrayList<>();
Region bounds = Region.obtain();
// top
bounds.set(mBounds);
bounds.op(0, 0, Integer.MAX_VALUE, getSafeInsetTop(), Region.Op.INTERSECT);
if (!bounds.isEmpty()) {
result.add(bounds.getBounds());
}
// left
bounds.set(mBounds);
bounds.op(0, 0, getSafeInsetLeft(), Integer.MAX_VALUE, Region.Op.INTERSECT);
if (!bounds.isEmpty()) {
result.add(bounds.getBounds());
}
// right & bottom
bounds.set(mBounds);
bounds.op(getSafeInsetLeft() + 1, getSafeInsetTop() + 1,
Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT);
if (!bounds.isEmpty()) {
result.add(bounds.getBounds());
}
bounds.recycle();
return result;
}
@Override
void drawTrack(Canvas canvas) {
final Drawable thumbDrawable = mThumb;
if (thumbDrawable != null && mSplitTrack) {
final Insets insets = thumbDrawable.getOpticalInsets();
final Rect tempRect = mTempRect;
thumbDrawable.copyBounds(tempRect);
tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
tempRect.left += insets.left;
tempRect.right -= insets.right;
final int saveCount = canvas.save();
canvas.clipRect(tempRect, Op.DIFFERENCE);
super.drawTrack(canvas);
drawTickMarks(canvas);
canvas.restoreToCount(saveCount);
} else {
super.drawTrack(canvas);
drawTickMarks(canvas);
}
}
private void maybeDrawHalo(@NonNull Canvas canvas, int width, int top) {
// Only draw the halo for devices that aren't using the ripple.
if (shouldDrawCompatHalo()) {
int centerX = (int) (trackSidePadding + normalizeValue(values.get(focusedThumbIdx)) * width);
if (VERSION.SDK_INT < VERSION_CODES.P) {
// In this case we can clip the rect to allow drawing outside the bounds.
canvas.clipRect(
centerX - haloRadius,
top - haloRadius,
centerX + haloRadius,
top + haloRadius,
Op.UNION);
}
canvas.drawCircle(centerX, top, haloRadius, haloPaint);
}
}
private void prepareCanvasForShadow(@NonNull Canvas canvas) {
// Calculate the translation to offset the canvas for the given offset and rotation.
int shadowOffsetX = getShadowOffsetX();
int shadowOffsetY = getShadowOffsetY();
// We only handle clipping as a convenience for older apis where we are trying to seamlessly
// provide fake shadows. On newer versions of android, we require that the parent is set so that
// clipChildren is false.
if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP && shadowBitmapDrawingEnable) {
// Add space and offset the canvas for the shadows. Otherwise any shadows drawn outside would
// be clipped and not visible.
Rect canvasClipBounds = canvas.getClipBounds();
canvasClipBounds.inset(-drawableState.shadowCompatRadius, -drawableState.shadowCompatRadius);
canvasClipBounds.offset(shadowOffsetX, shadowOffsetY);
canvas.clipRect(canvasClipBounds, Region.Op.REPLACE);
}
// Translate the canvas by an amount specified by the shadowCompatOffset. This will make the
// shadow appear at and angle from the shape.
canvas.translate(shadowOffsetX, shadowOffsetY);
}
/**
* Draw this BubbleTextView into the given Canvas.
*
* @param destCanvas the canvas to draw on
* @param padding the horizontal and vertical padding to use when drawing
*/
private void drawWithPadding(Canvas destCanvas, int padding) {
final Rect clipRect = mTempRect;
getDrawingRect(clipRect);
// adjust the clip rect so that we don't include the text label
clipRect.bottom =
getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + getLayout().getLineTop(0);
// Draw the View into the bitmap.
// The translate of scrollX and scrollY is necessary when drawing TextViews, because
// they set scrollX and scrollY to large values to achieve centered text
destCanvas.save();
destCanvas.scale(getScaleX(), getScaleY(),
(getWidth() + padding) / 2, (getHeight() + padding) / 2);
destCanvas.translate(-getScrollX() + padding / 2, -getScrollY() + padding / 2);
destCanvas.clipRect(clipRect, Op.REPLACE);
draw(destCanvas);
destCanvas.restore();
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
/**
* Sets the bitmap to be used for the zoomed view.
*/
public void setBitmap(Bitmap bitmap) {
if (mZoomedBitmap != null) {
mZoomedBitmap.recycle();
mZoomedBitmap = null;
}
mZoomedBitmap = bitmap;
// Round the corners of the bitmap so it doesn't stick out around the overlay.
Canvas canvas = new Canvas(mZoomedBitmap);
Path path = new Path();
RectF canvasRect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight());
float overlayCornerRadius = getOverlayCornerRadius(getContext());
path.addRoundRect(canvasRect, overlayCornerRadius, overlayCornerRadius, Direction.CCW);
canvas.clipPath(path, Op.XOR);
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
clearPaint.setColor(Color.TRANSPARENT);
canvas.drawPaint(clearPaint);
}
private WmDisplayCutout calculateDisplayCutoutForRotationUncached(
DisplayCutout cutout, int rotation) {
if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
return WmDisplayCutout.NO_CUTOUT;
}
if (rotation == ROTATION_0) {
return WmDisplayCutout.computeSafeInsets(
cutout, mInitialDisplayWidth, mInitialDisplayHeight);
}
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final List<Rect> bounds = WmDisplayCutout.computeSafeInsets(
cutout, mInitialDisplayWidth, mInitialDisplayHeight)
.getDisplayCutout().getBoundingRects();
transformPhysicalToLogicalCoordinates(rotation, mInitialDisplayWidth, mInitialDisplayHeight,
mTmpMatrix);
final Region region = Region.obtain();
for (int i = 0; i < bounds.size(); i++) {
final Rect rect = bounds.get(i);
final RectF rectF = new RectF(bounds.get(i));
mTmpMatrix.mapRect(rectF);
rectF.round(rect);
region.op(rect, Op.UNION);
}
return WmDisplayCutout.computeSafeInsets(DisplayCutout.fromBounds(region),
rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
rotated ? mInitialDisplayWidth : mInitialDisplayHeight);
}
private static Region boundingRectsToRegion(List<Rect> rects) {
Region result = Region.obtain();
if (rects != null) {
for (Rect r : rects) {
result.op(r, Region.Op.UNION);
}
}
return result;
}
/**
* Draws the {@link #mView} into the given {@param destCanvas}.
*/
private void drawDragView(Canvas destCanvas) {
destCanvas.save();
if (mView instanceof TextView) {
Drawable d = Workspace.getTextViewIcon((TextView) mView);
Rect bounds = getDrawableBounds(d);
destCanvas.translate(blurSizeOutline / 2 - bounds.left,
blurSizeOutline / 2 - bounds.top);
d.draw(destCanvas);
} else {
final Rect clipRect = mTempRect;
mView.getDrawingRect(clipRect);
boolean textVisible = false;
if (mView instanceof FolderIcon) {
// For FolderIcons the text can bleed into the icon area, and so we need to
// hide the text completely (which can't be achieved by clipping).
if (((FolderIcon) mView).getTextVisible()) {
((FolderIcon) mView).setTextVisible(false);
textVisible = true;
}
}
destCanvas.translate(-mView.getScrollX() + blurSizeOutline / 2,
-mView.getScrollY() + blurSizeOutline / 2);
destCanvas.clipRect(clipRect, Op.REPLACE);
mView.draw(destCanvas);
// Restore text visibility of FolderIcon if necessary
if (textVisible) {
((FolderIcon) mView).setTextVisible(true);
}
}
destCanvas.restore();
}
@Override
void drawTrack(Canvas canvas) {
if (mThumbStart != null && mSplitTrack) {
final Rect tempRect = mTempRect1;
mThumbStart.copyBounds(tempRect);
tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
tempRect.left += mThumbClipInset;
tempRect.right -= mThumbClipInset;
final int saveCount = canvas.save();
canvas.clipRect(tempRect, Op.DIFFERENCE);
mThumbEnd.copyBounds(tempRect);
tempRect.offset(mPaddingLeft - mThumbOffset, mPaddingTop);
tempRect.left += mThumbClipInset;
tempRect.right -= mThumbClipInset;
canvas.clipRect(tempRect, Op.DIFFERENCE);
super.drawTrack(canvas);
drawTickMarks(canvas);
canvas.restoreToCount(saveCount);
} else {
super.drawTrack(canvas);
drawTickMarks(canvas);
}
}
private void drawElevationShadow(Canvas canvas) {
canvas.save();
canvas.clipPath(maskEvaluator.getPath(), Op.DIFFERENCE);
if (VERSION.SDK_INT > VERSION_CODES.P) {
drawElevationShadowWithPaintShadowLayer(canvas);
} else {
drawElevationShadowWithMaterialShapeDrawable(canvas);
}
canvas.restore();
}
private void drawElevationShadow(Canvas canvas) {
canvas.save();
canvas.clipPath(maskEvaluator.getPath(), Op.DIFFERENCE);
if (VERSION.SDK_INT > VERSION_CODES.P) {
drawElevationShadowWithPaintShadowLayer(canvas);
} else {
drawElevationShadowWithMaterialShapeDrawable(canvas);
}
canvas.restore();
}
@Override
public Region getTransparentRegion() {
Rect bounds = getBounds();
transparentRegion.set(bounds);
calculatePath(getBoundsAsRectF(), path);
scratchRegion.setPath(path, transparentRegion);
transparentRegion.op(scratchRegion, Op.DIFFERENCE);
return transparentRegion;
}
/**
* Draw the View v into the given Canvas.
*
* @param v the view to draw
* @param destCanvas the canvas to draw on
* @param padding the horizontal and vertical padding to use when drawing
*/
private static void drawDragView(View v, Canvas destCanvas, int padding) {
final Rect clipRect = sTempRect;
v.getDrawingRect(clipRect);
boolean textVisible = false;
destCanvas.save();
if (v instanceof TextView) {
Drawable d = getTextViewIcon((TextView) v);
Rect bounds = getDrawableBounds(d);
clipRect.set(0, 0, bounds.width() + padding, bounds.height() + padding);
destCanvas.translate(padding / 2 - bounds.left, padding / 2 - bounds.top);
d.draw(destCanvas);
} else {
if (v instanceof FolderIcon) {
// For FolderIcons the text can bleed into the icon area, and so we need to
// hide the text completely (which can't be achieved by clipping).
if (((FolderIcon) v).getTextVisible()) {
((FolderIcon) v).setTextVisible(false);
textVisible = true;
}
}
destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
destCanvas.clipRect(clipRect, Op.REPLACE);
v.draw(destCanvas);
// Restore text visibility of FolderIcon if necessary
if (textVisible) {
((FolderIcon) v).setTextVisible(true);
}
}
destCanvas.restore();
}
protected void drawSubpatchContent(Canvas canvas)
{
canvas.save();
Matrix matrix = new Matrix();
matrix.postTranslate(x - HMargin, y - VMargin);
canvas.concat(matrix);
canvas.clipRect(new RectF(HMargin, VMargin, HMargin + dRect.width(), VMargin + dRect.height()), Op.INTERSECT);
for(Widget widget : widgets)
{
widget.draw(canvas);
}
canvas.restore();
}
public void draw(Canvas canvas) {
canvas.save();
canvas.clipRect(dRect.left, dRect.top, dRect.right, dRect.bottom + 1, Op.INTERSECT);
if (bg.draw(canvas)) {
paint.setColor(bgcolor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(dRect,paint);
paint.setColor(fgcolor);
paint.setStrokeWidth(1);
canvas.drawLine(dRect.left /*+ 1*/, dRect.top, dRect.right, dRect.top, paint);
canvas.drawLine(dRect.left /*+ 1*/, dRect.bottom, dRect.right, dRect.bottom, paint);
canvas.drawLine(dRect.left, dRect.top /*+ 1*/, dRect.left, dRect.bottom, paint);
canvas.drawLine(dRect.right, dRect.top /*+ 1*/, dRect.right, dRect.bottom, paint);
paint.setColor(fgcolor);
paint.setStrokeWidth(3);
if (horizontal) {
canvas.drawLine(Math.round(dRect.left + getNormalizedPosition() * dRect.width()), Math.round(dRect.top /*+ 2*/), Math.round(dRect.left + getNormalizedPosition() * dRect.width()), Math.round(dRect.bottom /*- 2*/), paint);
} else {
canvas.drawLine(Math.round(dRect.left /*+ 2*/), Math.round(dRect.bottom - getNormalizedPosition() * dRect.height()), Math.round(dRect.right /*- 2*/), Math.round(dRect.bottom - getNormalizedPosition() * dRect.height()), paint);
}
} else if (!slider.none()) {
if (horizontal) {
sRect.offsetTo(getNormalizedPosition() * (dRect.width() - sRect.width()) + dRect.left, dRect.top);
} else {
sRect.offsetTo(dRect.left, (1 - getNormalizedPosition()) * (dRect.height() - sRect.height()) + dRect.top);
}
slider.draw(canvas,sRect);
fg.draw(canvas);
}
canvas.restore();
drawLabel(canvas);
}
@Override
public void setClip_arrowSpace(Canvas canvas) {
/* Note: if we need midpt to depend on button locations or something,
* we can move the logic of this method to GUIHandler
* (in the same manner as timeToY and pitchToX) */
boolean fallingDown = false;
switch (Tools.gameMode) {
case Tools.STANDARD: fallingDown = false; break;
case Tools.REVERSE: fallingDown = true; break;
case Tools.OSU_MOD: setClip_screen(canvas); return;
}
int ymin, ymax, midpt;
switch (noteAppearance) {
case 1: //Hidden (appear, then disappear)
midpt = Tools.screen_h / 2 - Tools.button_h;
ymin = fallingDown ? 0 : (Tools.screen_h - midpt);
ymax = fallingDown ? midpt : Tools.screen_h;
break;
case 2: //Sudden (appear very late)
midpt = Tools.screen_h / 2 - Tools.button_h;
ymin = fallingDown ? midpt : 0;
ymax = fallingDown ? Tools.screen_h : (Tools.screen_h - midpt);
break;
case 3: // Invisible (never appear)
ymin = -1;
ymax = -1;
break;
case 0: default: //Visible (normal)
ymin = 0;
ymax = Tools.screen_h;
break;
}
canvas.clipRect(0, ymin, Tools.screen_w, ymax, Op.REPLACE);
}
private static void toRectAndAddToRegion(Path p, Region inoutRegion, Rect inoutRect) {
final RectF rectF = new RectF();
p.computeBounds(rectF, false /* unused */);
rectF.round(inoutRect);
inoutRegion.op(inoutRect, Op.UNION);
}
/**
* Draws a corner shadow on the canvas in the current bounds with the matrix transform applied.
*/
public void drawCornerShadow(
@NonNull Canvas canvas,
@Nullable Matrix matrix,
@NonNull RectF bounds,
int elevation,
float startAngle,
float sweepAngle) {
boolean drawShadowInsideBounds = sweepAngle < 0;
Path arcBounds = scratch;
if (drawShadowInsideBounds) {
cornerColors[0] = 0;
cornerColors[1] = shadowEndColor;
cornerColors[2] = shadowMiddleColor;
cornerColors[3] = shadowStartColor;
} else {
// Calculate the arc bounds to prevent drawing shadow in the same part of the arc.
arcBounds.rewind();
arcBounds.moveTo(bounds.centerX(), bounds.centerY());
arcBounds.arcTo(bounds, startAngle, sweepAngle);
arcBounds.close();
bounds.inset(-elevation, -elevation);
cornerColors[0] = 0;
cornerColors[1] = shadowStartColor;
cornerColors[2] = shadowMiddleColor;
cornerColors[3] = shadowEndColor;
}
float startRatio = 1f - (elevation / (bounds.width() / 2f));
float midRatio = startRatio + ((1f - startRatio) / 2f);
cornerPositions[1] = startRatio;
cornerPositions[2] = midRatio;
cornerShadowPaint.setShader(
new RadialGradient(
bounds.centerX(),
bounds.centerY(),
bounds.width() / 2,
cornerColors,
cornerPositions,
Shader.TileMode.CLAMP));
// TODO(b/117606382): handle oval bounds by scaling the canvas.
canvas.save();
canvas.concat(matrix);
if (!drawShadowInsideBounds) {
canvas.clipPath(arcBounds, Op.DIFFERENCE);
// This line is required for the next drawArc to work correctly, I think.
canvas.drawPath(arcBounds, transparentPaint);
}
canvas.drawArc(bounds, startAngle, sweepAngle, true, cornerShadowPaint);
canvas.restore();
}
@Override
public void draw(Canvas canvas) {
if (!mShadowsEnabled) {
super.draw(canvas);
return;
}
final Drawable background = mBackground;
if (background != null) {
final int scrollX = getScrollX();
final int scrollY = getScrollY();
if (mBackgroundSizeChanged) {
background.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop());
mBackgroundSizeChanged = false;
}
if ((scrollX | scrollY) == 0) {
background.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
// If text is transparent, don't draw any shadow
if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) {
getPaint().clearShadowLayer();
super.draw(canvas);
return;
}
// We enhance the shadow by drawing the shadow twice
getPaint().setShadowLayer(SHADOW_LARGE_RADIUS, 0.0f, SHADOW_Y_OFFSET, SHADOW_LARGE_COLOUR);
super.draw(canvas);
canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(),
getScrollX() + getWidth(),
getScrollY() + getHeight(), Region.Op.INTERSECT);
getPaint().setShadowLayer(SHADOW_SMALL_RADIUS, 0.0f, 0.0f, SHADOW_SMALL_COLOUR);
super.draw(canvas);
canvas.restore();
}
Bitmap createMediumDropShadow(BubbleTextView view) {
final Bitmap result = Bitmap.createBitmap(
view.getWidth() + shadowBitmapPadding + shadowBitmapPadding,
view.getHeight() + shadowBitmapPadding + shadowBitmapPadding + mShadowOffset,
Bitmap.Config.ARGB_8888);
mCanvas.setBitmap(result);
final Rect clipRect = sTempRect;
view.getDrawingRect(sTempRect);
// adjust the clip rect so that we don't include the text label
clipRect.bottom = view.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V
+ view.getLayout().getLineTop(0);
// Draw the View into the bitmap.
// The translate of scrollX and scrollY is necessary when drawing TextViews, because
// they set scrollX and scrollY to large values to achieve centered text
mCanvas.save();
mCanvas.scale(view.getScaleX(), view.getScaleY(),
view.getWidth() / 2 + shadowBitmapPadding,
view.getHeight() / 2 + shadowBitmapPadding);
mCanvas.translate(-view.getScrollX() + shadowBitmapPadding,
-view.getScrollY() + shadowBitmapPadding);
mCanvas.clipRect(clipRect, Op.REPLACE);
view.draw(mCanvas);
mCanvas.restore();
int[] blurOffst = new int[2];
mBlurPaint.setMaskFilter(mShaowBlurMaskFilter);
Bitmap blurBitmap = result.extractAlpha(mBlurPaint, blurOffst);
mCanvas.save();
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mCanvas.translate(blurOffst[0], blurOffst[1]);
mDrawPaint.setColor(Color.BLACK);
mDrawPaint.setAlpha(30);
mCanvas.drawBitmap(blurBitmap, 0, 0, mDrawPaint);
mDrawPaint.setAlpha(60);
mCanvas.drawBitmap(blurBitmap, 0, mShadowOffset, mDrawPaint);
mCanvas.restore();
mCanvas.setBitmap(null);
blurBitmap.recycle();
return result;
}
@Override
public void setClip_screen(Canvas canvas) {
//canvas.clipRect(0, 0, canvas.getWidth(), canvas.getHeight(), Op.REPLACE);
canvas.clipRect(0, 0, Tools.screen_w, Tools.screen_h, Op.REPLACE);
}
public void draw(GUIDrawingArea drawarea, Canvas canvas) {
//first-press arrow and release arrow boxes
int start_rect_top = drawarea.timeToY(start_time);
//int start_rect_bottom = start_rect_top + Tools.button_h;
int end_rect_top = drawarea.timeToY(end_time);
int end_rect_bottom = end_rect_top + Tools.button_h;
int rect_left = drawarea.pitchToX(pitch);
int rect_right = rect_left + Tools.button_w;
int win_h = canvas.getHeight();
//int win_w = canvas.getWidth();
boolean fallingDown = start_rect_top > end_rect_top;
int hold_rect_top, hold_rect_bottom; //bounding box for hold rectangle
int hold_draw_start, hold_draw_end, hold_draw_add; // parameters to draw loop
if (fallingDown) { //arrows falling down
hold_rect_top = end_rect_top + Tools.button_h/2;
hold_rect_bottom = start_rect_top + Tools.button_h/2;
hold_draw_start = drawarea.timeToY(original_starttime) + Tools.button_h / 2 - holdimg_h;
hold_draw_end = ((end_rect_top > 0) ? end_rect_top : 0) - holdimg_h;
hold_draw_add = -holdimg_h;
} else { //arrows rising up
hold_rect_top = start_rect_top + Tools.button_h/2;
hold_rect_bottom = end_rect_top + Tools.button_h/2;
hold_draw_start = drawarea.timeToY(original_starttime) + Tools.button_h / 2;
hold_draw_end = ((end_rect_bottom < win_h) ? end_rect_bottom : win_h);
hold_draw_add = holdimg_h;
}
//body
Path path = new Path();
//TODO diagonal clip paths for up/down arrows (straight for left/right)
path.addRect(rect_left, hold_rect_top, rect_right, hold_rect_bottom, Direction.CCW);
canvas.clipPath(path, Op.INTERSECT);
//need to swap comparison direction based on motion direction, hence xor
for (int y = hold_draw_start; (y <= hold_draw_end) ^ fallingDown; y += hold_draw_add) {
canvas.drawBitmap(
drawarea.getBitmap(
holdRsrc(mode, false),
Tools.button_w, holdimg_h
),
rect_left, y, null);
}
drawarea.setClip_arrowSpace(canvas);
//end arrow (top)
canvas.drawBitmap(
drawarea.getBitmap(
holdRsrc(mode, true),
Tools.button_w, Tools.button_h
),
rect_left, end_rect_top, null
);
//start arrow (bottom)
canvas.drawBitmap(
drawarea.getBitmap(
GUINoteImage.rsrc(pitch, fraction, clicked),
Tools.button_w, Tools.button_h
),
rect_left, start_rect_top, null
);
//debug
/*Paint p = new Paint();
switch (mode) {
case INACTIVE: p.setARGB(127, 0, 255, 0); break;
case ACTIVE: p.setARGB(200, 0, 255, 0); break;
case DEAD: p.setARGB(127, 127, 127, 127); break;
}
canvas.drawRect(new Rect(rect_left, end_rect_top, rect_right, start_rect_bottom), p);*/
}
@Override
public boolean clipPath(SafeTranslatedPath path, Op op) {
return getWrappedCanvas().clipPath(path, op);
}
@Override
public boolean clipRect(final double left, final double top, final double right,
final double bottom, final Op op) {
return getWrappedCanvas().clipRect((float) (left + xOffset), (float) (top + yOffset),
(float) (right + xOffset), (float) (bottom + yOffset), op);
}
@Override
public boolean clipRect(final Rect rect, final Op op) {
rect.offset(xOffset, yOffset);
return getWrappedCanvas().clipRect(rect, op);
}
@Override
public boolean clipRegion(final Region region, final Op op) {
region.translate(xOffset, yOffset);
return getWrappedCanvas().clipRegion(region, op);
}