blob: 3beb3a642ef5446edf499c7c13c0ab4faa7fc57e [file] [log] [blame]
// Copyright 2018 The Feed Authors.
//
// 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.google.android.libraries.feed.piet.ui;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.support.annotation.IntDef;
import android.support.annotation.VisibleForTesting;
import android.util.LruCache;
/** Caches rounded corner masks to save memory and time spent creating them */
public class RoundedCornerMaskCache {
// TODO: Make cache size configurable.
private static final int CACHE_SIZE = 8;
@IntDef({Corner.TOP_LEFT, Corner.TOP_RIGHT, Corner.BOTTOM_LEFT, Corner.BOTTOM_RIGHT})
@interface Corner {
int TOP_LEFT = 0;
int TOP_RIGHT = 1;
int BOTTOM_LEFT = 2;
int BOTTOM_RIGHT = 3;
}
private final Canvas canvas;
private final Paint paint;
private final Paint maskPaint;
private final LruCache<Integer, RoundedCornerBitmaps> cache;
public RoundedCornerMaskCache() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
canvas = new Canvas();
cache =
new LruCache<Integer, RoundedCornerBitmaps>(CACHE_SIZE) {
@Override
protected RoundedCornerBitmaps create(Integer key) {
return new RoundedCornerBitmaps(key, canvas, maskPaint);
}
};
}
Paint getPaint() {
return paint;
}
Paint getMaskPaint() {
return maskPaint;
}
RoundedCornerBitmaps getMasks(int radius) {
RoundedCornerBitmaps masks = cache.get(radius);
if (masks == null) {
masks = new RoundedCornerBitmaps(radius, canvas, maskPaint);
cache.put(radius, masks);
}
return masks;
}
public void purge() {
cache.evictAll();
}
static class RoundedCornerBitmaps {
@VisibleForTesting final Bitmap[] masks;
private final Canvas canvas;
private final int radius;
private final Paint maskPaint;
RoundedCornerBitmaps(int radius, Canvas canvas, Paint maskPaint) {
masks = new Bitmap[4];
this.canvas = canvas;
this.radius = radius;
this.maskPaint = maskPaint;
}
Bitmap get(@Corner int corner) {
switch (corner) {
case Corner.TOP_LEFT:
if (masks[Corner.TOP_LEFT] == null) {
masks[Corner.TOP_LEFT] = Bitmap.createBitmap(radius, radius, Config.ALPHA_8);
canvas.setBitmap(masks[Corner.TOP_LEFT]);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(radius, radius, radius, maskPaint);
}
return masks[Corner.TOP_LEFT];
case Corner.TOP_RIGHT:
if (masks[Corner.TOP_RIGHT] == null) {
masks[Corner.TOP_RIGHT] = Bitmap.createBitmap(radius, radius, Config.ALPHA_8);
canvas.setBitmap(masks[Corner.TOP_RIGHT]);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(0, radius, radius, maskPaint);
}
return masks[Corner.TOP_RIGHT];
case Corner.BOTTOM_LEFT:
if (masks[Corner.BOTTOM_LEFT] == null) {
masks[Corner.BOTTOM_LEFT] = Bitmap.createBitmap(radius, radius, Config.ALPHA_8);
canvas.setBitmap(masks[Corner.BOTTOM_LEFT]);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(radius, 0, radius, maskPaint);
}
return masks[Corner.BOTTOM_LEFT];
case Corner.BOTTOM_RIGHT:
if (masks[Corner.BOTTOM_RIGHT] == null) {
masks[Corner.BOTTOM_RIGHT] = Bitmap.createBitmap(radius, radius, Config.ALPHA_8);
canvas.setBitmap(masks[Corner.BOTTOM_RIGHT]);
canvas.drawColor(Color.BLACK);
canvas.drawCircle(0, 0, radius, maskPaint);
}
return masks[Corner.BOTTOM_RIGHT];
default:
throw new IllegalArgumentException(String.format("Unrecognized corner: %s", corner));
}
}
}
}