|
|
|
|
@ -5,45 +5,67 @@ 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 androidx.annotation.StyleRes
|
|
|
|
|
import androidx.core.content.withStyledAttributes
|
|
|
|
|
import androidx.core.graphics.ColorUtils
|
|
|
|
|
import androidx.core.graphics.withClip
|
|
|
|
|
import com.google.android.material.color.MaterialColors
|
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
|
import kotlin.math.absoluteValue
|
|
|
|
|
|
|
|
|
|
class FaviconFallbackDrawable(
|
|
|
|
|
class FaviconDrawable(
|
|
|
|
|
context: Context,
|
|
|
|
|
@StyleRes styleResId: Int,
|
|
|
|
|
name: String,
|
|
|
|
|
) : Drawable() {
|
|
|
|
|
|
|
|
|
|
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
|
|
|
private var colorBackground = Color.WHITE
|
|
|
|
|
private var colorStroke = Color.LTGRAY
|
|
|
|
|
private val letter = name.take(1).uppercase()
|
|
|
|
|
private val color = MaterialColors.harmonizeWithPrimary(context, colorOfString(name))
|
|
|
|
|
private var cornerSize = 0f
|
|
|
|
|
private var colorForeground = Color.DKGRAY
|
|
|
|
|
private val textBounds = Rect()
|
|
|
|
|
private val tempRect = Rect()
|
|
|
|
|
private val boundsF = RectF()
|
|
|
|
|
private val clipPath = Path()
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
|
paint.style = Paint.Style.FILL
|
|
|
|
|
context.withStyledAttributes(styleResId, R.styleable.FaviconFallbackDrawable) {
|
|
|
|
|
colorBackground = getColor(R.styleable.FaviconFallbackDrawable_backgroundColor, colorBackground)
|
|
|
|
|
colorStroke = getColor(R.styleable.FaviconFallbackDrawable_strokeColor, colorStroke)
|
|
|
|
|
cornerSize = getDimension(R.styleable.FaviconFallbackDrawable_cornerSize, cornerSize)
|
|
|
|
|
paint.strokeWidth = getDimension(R.styleable.FaviconFallbackDrawable_strokeWidth, 0f) * 2f
|
|
|
|
|
}
|
|
|
|
|
paint.textAlign = Paint.Align.CENTER
|
|
|
|
|
paint.isFakeBoldText = true
|
|
|
|
|
colorForeground = MaterialColors.harmonize(colorOfString(name), colorBackground)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun draw(canvas: Canvas) {
|
|
|
|
|
val cx = bounds.exactCenterX()
|
|
|
|
|
paint.color = color
|
|
|
|
|
canvas.drawPaint(paint)
|
|
|
|
|
paint.color = Color.WHITE
|
|
|
|
|
val ty = bounds.height() / 2f + textBounds.height() / 2f - textBounds.bottom
|
|
|
|
|
canvas.drawText(letter, cx, ty, paint)
|
|
|
|
|
if (cornerSize > 0f) {
|
|
|
|
|
canvas.withClip(clipPath) {
|
|
|
|
|
doDraw(canvas)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
doDraw(canvas)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onBoundsChange(bounds: Rect) {
|
|
|
|
|
super.onBoundsChange(bounds)
|
|
|
|
|
boundsF.set(bounds)
|
|
|
|
|
val innerWidth = bounds.width() - (paint.strokeWidth * 2f)
|
|
|
|
|
paint.textSize = getTextSizeForWidth(innerWidth, letter) * 0.5f
|
|
|
|
|
paint.getTextBounds(letter, 0, letter.length, textBounds)
|
|
|
|
|
invalidateSelf()
|
|
|
|
|
clipPath.reset()
|
|
|
|
|
clipPath.addRoundRect(boundsF, cornerSize, cornerSize, Path.Direction.CW)
|
|
|
|
|
clipPath.close()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun setAlpha(alpha: Int) {
|
|
|
|
|
@ -58,6 +80,24 @@ class FaviconFallbackDrawable(
|
|
|
|
|
@Deprecated("Deprecated in Java")
|
|
|
|
|
override fun getOpacity() = PixelFormat.TRANSPARENT
|
|
|
|
|
|
|
|
|
|
private fun doDraw(canvas: Canvas) {
|
|
|
|
|
// background
|
|
|
|
|
paint.color = colorBackground
|
|
|
|
|
paint.style = Paint.Style.FILL
|
|
|
|
|
canvas.drawPaint(paint)
|
|
|
|
|
// letter
|
|
|
|
|
paint.color = colorForeground
|
|
|
|
|
val cx = (boundsF.left + boundsF.right) * 0.6f
|
|
|
|
|
val ty = boundsF.bottom * 0.7f + textBounds.height() * 0.5f - textBounds.bottom
|
|
|
|
|
canvas.drawText(letter, cx, ty, paint)
|
|
|
|
|
if (paint.strokeWidth > 0f) {
|
|
|
|
|
// stroke
|
|
|
|
|
paint.color = colorStroke
|
|
|
|
|
paint.style = Paint.Style.STROKE
|
|
|
|
|
canvas.drawPath(clipPath, paint)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun getTextSizeForWidth(width: Float, text: String): Float {
|
|
|
|
|
val testTextSize = 48f
|
|
|
|
|
paint.textSize = testTextSize
|